for 현쪽이
select blocks, bytes/1024/1024 mb
from dba_segments
where segment_name = 'REDO_TABLE';
redo_table 이 사용하고 있는 블록 수 조회해보기
(테이블 만들고 인서트 작업을 했다가 도로 롤백했지만
사용했던 블록은 그대로 남아 있다.)
BLOCKS MB
-------------------------------
1408 11
그럼 이제 새로운 세션을 열어서 새로운 시뮬레이션을 돌려보자.
★ 시나리오 2
<<new sys>>
1. 리두 통계정보 보기
창을 새로 열었기 때문에 통계정보가 없다.
SYS@ora11g> select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;
NAME SUM(S.VALUE)
----------------------------------------------------------------------------------
redo entries 0
redo size 0
redo log space requests 0
redo log space wait time 0
redo synch writes 0
redo blocks written 0
redo writes 0
7 rows selected.
2. 대량의 데이터 인서트 작업하기... 그런데 이제 append 라는 힌트를 곁들인
SYS@ora11g> insert /*+ append */
into hr.redo_table(id, name)
select object_id, object_name from dba_objects;
86845 rows created.
3. 언두와 리두에 대한 정보 보기
: append 라는 힌트를 쓴 덕분에 언두와 리두가 엄청 적게 발생함
SYS@ora11g> select t.used_ublk, t.used_urec
from v$transaction t, v$session s
where s.sid = (select sid from v$mystat where rownum = 1)
and s.taddr = t.addr;
USED_UBLK USED_UREC
------------------------------------------------
2 2
아까랑 비교해보기
아까는 used_ublk 수 44, used_urec 수 2489 였는데 확연히 줄어든 것이 보인다.
4. 리두 발생량 확인하기
리두 발생량도 훨씬 줄어들어 있다.
SYS@ora11g>
select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;
NAME SUM(S.VALUE)
------------------------------------------------------------------------------------
redo entries 1596
redo size 11042332
redo log space requests 4
redo log space wait time 8
redo synch writes 1
redo blocks written 0
redo writes 0
7 rows selected.
5. 사용하고 있는 블록 수 다시 조회해보기
SYS@ora11g> select blocks, bytes/1024/1024 mb
from dba_segments
where segment_name = 'REDO_TABLE';
BLOCKS MB
-------------------------------
2816 22
이게 아까의 결과인데
아까의 2배로 늘었다.
append 를 썼더니 언두 발생량도 줄고 리두 발생량도 줄었는데
블록은 2배로 늘어난 이유는 다음과 같다 ↓
처음에 테이블을 만들고 인서트 작업하게 되면
min extent 가 만들어지고 (extent 크기가 64K 이면 8K 짜리 블록 8개들이 extent 가 된다)
HWM 는 5배수 단위로 찍히므로 5번째 블록과 6번째 블록 사이에 찍혀있게 되는데
HWM 까지 꽉 차면 > min extent 를 하나 더 만들고
> HWM 뒤로 밀림 > HWM는 10번째 블록과 11번째 블록 사이에 찍힌다.
첫번째 인서트 작업을 할 때
테이블에 대량의 데이터가 계속 들어가면서 min extent 만들어지고, HWM 뒤로 밀리고...
이런 일이 계속 반복되면서 1408 번째 블록까지 쓰게 됐는데
rollback 하면서 블록 안에 있던 내용은 없어졌지만
쓰던 블록은 그대로 있고 + HWM 도 저~~~~~ 뒤에 찍혀 있는데
여기서 다시 인서트 작업을 하게 되면
새로 인서트하는 데이터는 앞에 있는 블록들 중 아무곳에나 들어가게 된다.
그런데 append 힌트를 쓰면: 하이워터 마크가 찍힌 부분 뒤에 새롭게 extent 를 할당받아서 insert 작업을 하게 된다.
(원래의 append 의 의미처럼 제일 뒤에 추가하게 됨)
그래서 속도가 매우 빠르다.
앞부분 블록은 비어있지만 인서트 작업을 하려면 따로 비어있는 블록을 찾아보고 추가하는 작업을 해야 하는데
뒷부분에 새로 extent 를 만들고 넣으면 빈 블록을 찾아보는 작업을 할 필요가 없어서 빠르게 작업할 수 있다.
그렇지만 앞부분은 다 빈 공간인데 하나도 안씀 > 앞부분의 블록이 낭비된다.
풀 테이블 스캔할 때 액세스해야 하는 블록이 많아져서 큰 문제가 된다.
(append 를 쓰면 작업이 빨라지긴 하지만 알고 써야 한다.)
6. 롤백
SYS@ora11g> rollback;
Rollback complete.
7. 통계정보 보기
별로 많이 늘어나지 않았다.
SYS@ora11g>
select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;
NAME SUM(S.VALUE)
---------------------------------------------------------------- ------------
redo entries 1598
redo size 11042680
redo log space requests 4
redo log space wait time 8
redo synch writes 2
redo blocks written 0
redo writes 0
7 rows selected.
8. 테이블 truncate
SYS@ora11g> truncate table hr.redo_table;
Table truncated.
9. 블록 수 조회해보기
SYS@ora11g> select blocks, bytes/1024/1024 mb
from dba_segments
where segment_name = 'REDO_TABLE';
BLOCKS MB
-------------------------------
8 .0625
min extent (64K) 하나만 놔두고 다 없어졌다.
(min extent = extent 1개 = 64K = 8K 짜리 테이블 8개들이 모음)
truncate 대상 테이블이 있고, truncate 대상 테이블에 대량의 데이터를 부어넣는 작업을 종종 하는데
append 힌트를 써서 넣으면 언두와 리두 발생량을 줄일 수 있다.
(원본데이터를 다른 테이블이 가지고 있는 경우 append 힌트 쓰는 것이 낫다)
★ 리두를 그래도 더 줄이고 싶다면?
노로깅 모드로 바꾸기
또다시 새로운 세션에서
<<new session>>
1. 리두정보 확인: 세션을 새로 열었기 때문에 다 0 으로 나온다.
SYS@ora11g> select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;
NAME SUM(S.VALUE)
-------------------------------------------------------------------------------------
redo entries 0
redo size 0
redo log space requests 0
redo log space wait time 0
redo synch writes 0
redo blocks written 0
redo writes 0
7 rows selected.
2. 테이블이 로깅모드로 되어있는지 노로깅 모드로 되어있는지 확인
로깅모드로 되어 있다 (YES) : 테이블에 DML 작업할 때마다 무조건 리두 정보 만든다.
SYS@ora11g> select logging from dba_tables where table_name = 'REDO_TABLE';
LOG
--------
YES
3. 노로깅 모드로 바꾸기
이제부터 인서트 작업을 통해 저 테이블에 대량의 데이터를 부어넣으려고 하는데
리두를 줄이고 싶어서 바꿔주는 것
SYS@ora11g> alter table hr.redo_table nologging;
Table altered.
바뀌었는지 확인하기
SYS@ora11g> select logging from dba_tables where table_name = 'REDO_TABLE';
LOG
---------
NO
4. 리두 정보 보기
SYS@ora11g> select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;
NAME SUM(S.VALUE)
-------------------------------------------------------------------------------------
redo entries 6
redo size 2252
redo log space requests 0
redo log space wait time 0
redo synch writes 1
redo blocks written 0
redo writes 0
7 rows selected.
노로깅모드로 바꾸기만 했을 뿐인데도 리두정보가 만들어져 있는 것이 보인다.
왜냐하면 alter 문장을 수행하면서 테이블과 관련된 딕셔너리 정보들에 갱신조작이 발생했고
커밋이 내부적으로 돌아갔기 때문 (그래서 redo synch writes 값이 1)
다시 나갔다가 새로 접속해보자.
★ 시나리오 3
<<new_1>>
1. 리두정보 확인: 세션을 새로 열었기 때문에 다 0 으로 나온다.
SYS@ora11g> select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;
NAME SUM(S.VALUE)
-------------------------------------------------------------------------------------
redo entries 0
redo size 0
redo log space requests 0
redo log space wait time 0
redo synch writes 0
redo blocks written 0
redo writes 0
2. 인서트 작업
SYS@ora11g> insert /*+ append */
into hr.redo_table(id, name)
select object_id, object_name from dba_objects;
86845 rows created.
3. 언두 발생량 확인하기
SYS@ora11g> select t.used_ublk, t.used_urec
from v$transaction t, v$session s
where s.sid = (select sid from v$mystat where rownum = 1)
and s.taddr = t.addr;
USED_UBLK USED_UREC
-----------------------------------------
1 1
4. 리두 통계정보 (리두 발생량이 얼마나 줄었는지) 보기
SYS@ora11g> select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;
NAME SUM(S.VALUE)
---------------------------------------------------------------------------------
redo entries 419
redo size 50244
redo log space requests 0
redo log space wait time 0
redo synch writes 1
redo blocks written 0
redo writes 0
7 rows selected.
5. 사용한 블록의 수 확인: 처음과 똑같다. (truncate 하고 나서 했기 때문에)
SYS@ora11g> select blocks, bytes/1024/1024 mb
from dba_segments
where segment_name = 'REDO_TABLE';
BLOCKS MB
------------------------------
1408 11
6. 롤백
SYS@ora11g> rollback;
Rollback complete.
7. 롤백 후 리두발생량 보기
SYS@ora11g> select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;
NAME SUM(S.VALUE)
--------------------------------------------------------------------------------
redo entries 420
redo size 50324
redo log space requests 0
redo log space wait time 0
redo synch writes 2
redo blocks written 0
redo writes 0
7 rows selected.
8. 테이블 truncate
SYS@ora11g> truncate table hr.redo_table;
Table truncated.
9. 블록 사용량 보기
SYS@ora11g> select blocks, bytes/1024/1024 mb
from dba_segments
where segment_name = 'REDO_TABLE';
BLOCKS MB
------------------------------
8 .0625
10. 테이블 로깅모드로 바꾸기
SYS@ora11g> alter table hr.redo_table logging;
Table altered.
확인
SYS@ora11g> select logging from dba_tables where table_name = 'REDO_TABLE';
LOG
-------
YES
테이블 리두를 만들기 싫으면: 노로깅 모드로
다만 이렇게 하면 인스턴스 실패가 발생했을 경우 리두 없어서 복구를 못할 수도 있다.
(꼭 주의해서 사용해야 함!!!!!)
그렇지만 테이블에 대량의 데이터를 부어넣을 때는 리두가 필요 없으므로 노로깅 모드가 유용하다.
★ 요약
insert 하면: HWM 앞부분에 비어있는 곳을 찾아서 넣기 때문에 시간이 많이 걸린다.
그렇지만 append 힌트를 쓰면: HWM 뒤에 있는 블록에 insert 한다.
2024년 2월 14일 (발렌타인데이 ㅠㅠ) 1교시 (0) | 2024.02.14 |
---|---|
2024년 2월 8일 1교시 (0) | 2024.02.08 |
2024년 2월 7일 4교시 (0) | 2024.02.07 |
2024년 2월 7일 1교시 (0) | 2024.02.07 |
2024년 2월 2일 6교시 실행계획 무효화 (0) | 2024.02.02 |