-- SYS.X$KCBKPFS 정보
SYS@ORACLE11> select * from X$KCBKPFS where PREFETCH_BLOCKS > 0;
ADDR INDX INST_ID BUFFER_POOL_ID TIMESTAMP PREFETCH_OPS PREFETCH_BLOCKS WASTED_BLOCKS CLIENTS_PREFETCH PREFETCH_LIMIT
---------------- ---------- ---------- -------------- ---------- ------------ --------------- ------------- ---------------- --------------
00007F5CB70ED540 100 1 3 6517084 53 312 0 1 5319
SUNSHINY@ORACLE11> select name, value from v$sysstat
2 where name in ('physical reads cache prefetch','prefetched blocks aged out before use');
NAME VALUE
---------------------------------------------------------------- ----------
physical reads cache prefetch 8613
prefetched blocks aged out before use 0
WAIT #2: nam='db file scattered read' ela= 16809 file#=511 block#=46077 blocks=4 obj#=79955 tim=245420303473
WAIT #2: nam='db file parallel read' ela= 1166 file#=1 blocks=5 requests=5 obj#=79955 tim=245422093812
WAIT #2: nam='db file parallel read' ela= 14151 file#=1 blocks=2 requests=2 obj#=79955 tim=245429134621
WAIT #2: nam='db file scattered read' ela= 9371 file#=580 block#=45357 blocks=1 obj#=79955 tim=245440385315
WAIT #2: nam='db file parallel read' ela= 13349 file#=1 blocks=4 requests=4 obj#=79955 tim=245447176624
WAIT #2: nam='db file parallel read' ela= 13180 file#=1 blocks=4 requests=4 obj#=79955 tim=245454432524
오라클 7.2 버전부터 사용돼 온 기능이다.
브랜치 블록에서 앞으로 읽게 될 리프 블록 주소를 미리 얻을 수 있으므로 I/O Call이 필요한 시점에 미리 캐싱해 두는 것이 가능하다.
① -> ② -> ③ -> ④ 순으로 Index Range Scan을 진행
2번 브랜치 블록을 읽고 5번 리프 블록을 읽으려는 시점에 5번 블록이 버퍼 캐시에 없으면 물리적인 디스크 I/O가 필요
이때 6,7번 블록까지 같이 적재해 놓는다면, "④"번 작업 수행 시 리프 블록 스캔이 진행하는 동안 디스크 I/O때문에 대기할 가능성을 줄일 수 있다.
인덱스 Prefetch 기능이 가장 효과적일 수 있는 상황은 Index Full Scan이 일어날 때다.
부분 범위 처리 방식으로 중간에 멈추지만 않는다면 모든 인덱스 리프 블록을 읽게 되기 때문이다.
Index Full Scan시 Prefetch 방식으로 I/O하려면 리프 블록 위쪽에 있는 브랜치 블록들을 추가로 읽어야 하기 때문에 Prefetch하지 않을 때 보다 I/O가 약간 더 발생한다.(일반적인 Index Full Scan 시에는 가장 왼쪽 브랜치 블록만 읽는다.)
Prefetch를 제어하는 파라미터
'테이블 Lookup Prefetch' 또는 '데이터 블록 Prefetch'라고도 한다.
인덱스를 경유해 테이블 레코드를 액세스하는 도중 디스크에서 캐시로 블록을 적재해야 하는 상황이 발생할 수 있는데, 그때 다른 테이블 블록까지 미리 적재해 두는 기능이다.
리프 블록에 있는 인덱스 레코드는 논리적인 순서를 따라 읽는다. 읽는 도중에 디스크 I/O가 필요해지면 현재 읽던 리프 블록 내에서 앞으로 액세스해야 할 테이블 블록 주소 목록을 미리 취합 할 수 있다.
① -> ② -> ③ -> ④ -> ⑤ -> ⑥ -> ⑦순서로 진행된다.
5번 인덱스 리프 블록을 읽고 12번 테이블 블록을 읽으려는 시점에 12번 블록이 버퍼 캐시에 없으면 물리적인 디스크 I/O가 필요하다.
이때, 13, 15, 18번 블록까지 같이 적재해 놓는 다면 ⑤,⑥,⑦번 액세스 시에 디스크 I/O 때문에 대기하지 않아도 된다.
Random 액세스 성능을 향상시키려고 버퍼 Pinning과 테이블 Prefetch 같은 기능을 사용한다.
버퍼 Pinning은 Random 액세스에 의한 논리적 블록 요청 횟수를 감소시키고, 테이블 Prefetch는 디스크 I/O에 의한 대기 횟수를 감소 시킨다.
이 기능은 인덱스 클러스터링 팩터가 나쁠 때 특히 효과적으로 사용할 수 있다. 클러스터링 팩터가 나쁘면 논리적 I/O가 증가할 뿐 아니라 디스크 I/O도 많이 발생하기 때문이다.
테이블 Prefetch를 제어하는 파라미터는 아래와 같다.
이 자료는 (오라클 성능 고도화 원리와해법 I)을 참고 하여 작성했습니다.