\-테이블 풀 스캔 후 대부분이 필터링되고 일부만 선택된다면 인덱스를 이용하는 것이 효과적.
\-참조 컬럼이 모두 인덱스 안에 있으면 인덱스 range scan 만으로 결과를 얻을 수 있다.
\-인덱스의 컬럼 순서에 따라서도 range scan 의 선택도가 달라짐
동일한 결과를 얻기 위해 더 많은 leaf block 을 읽어야 함
\-인덱스가 속하지 않는 컬럼을 Select 참조 시 인덱스 \-> 테이블 간 random access 발생
select /*+ index(t ind1) */ count(*) from test1 t ^M
where owner like 'SYS%' and object_name='ALL_OBJECTS'
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 4 0.00 0.00 0 2 0 0
Execute 4 0.00 0.00 0 0 0 0
Fetch 8 0.06 0.14 80 4064 0 4
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 16 0.06 0.14 80 4066 0 4
Misses in library cache during parse: 2
Optimizer mode: ALL_ROWS
Parsing user id: 84
Number of plan statistics captured: 4
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 SORT AGGREGATE (cr=1016 pr=20 pw=0 time=36844 us)
1 1 1 TABLE ACCESS BY INDEX ROWID TEST1 (cr=1016 pr=20 pw=0 time=36834 us cost=237 size=5478 card=66)
37094 37094 37094 INDEX RANGE SCAN IND1 (cr=81 pr=20 pw=0 time=19669 us cost=23 size=0 card=47568)(object id 526155)
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 4 0.00 0.00 0 2 0 0
Execute 4 0.00 0.00 0 0 0 0
Fetch 8 0.06 0.14 80 4064 0 4
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 16 0.06 0.14 80 4066 0 4
Single block I/O
정의
SQL> select name, value from v$sysstat
where name in ('physical reads cache prefetch','prefetched blocks aged out before use');
NAME VALUE
---------------------------------------------------------------- -----------
physical reads cache prefetch 214298948
prefetched blocks aged out before use 31027630
2 rows selected.
\_db_file_noncontig_mblock_read_count
한 번에 최대 몇 개 블록을 프리패치 할지 결정
1 지정 시 기능 정지
SQL> select ksppinm name,
2 ksppstvl value,
3 decode(bitand(ksppiflg/256,1),1,'true','false') ses_modifiable,
4 decode(bitand(ksppiflg/65536,3),1,'immediate',2,'deferred',3,'immediate','false') sys_modifiable,
5 ksppdesc description
6 from sys.x$ksppi i, sys.x$ksppcv v
7 where i.indx = v.indx
8* and i.ksppinm in ('_index_prefetch_factor', '_db_file_noncontig_mblock_read_count')
SQL> /
NAME VALUE SES_M SYS_MODIF DESCRIPTION
-------------------------------------------------- ---------- ----- --------- --------------------------------------------------------------------------------
_db_file_noncontig_mblock_read_count 11 false false number of noncontiguous db blocks to be prefetched
_index_prefetch_factor 100 true immediate index prefetching factor
SQL>
SQL> select ksppinm name,
2 ksppstvl value,
3 decode(bitand(ksppiflg/256,1),1,'true','false') ses_modifiable,
4 decode(bitand(ksppiflg/65536,3),1,'immediate',2,'deferred',3,'immediate','false') sys_modifiable,
5 ksppdesc description
6 from sys.x$ksppi i, sys.x$ksppcv v
7 where i.indx = v.indx
8* and i.ksppinm in ('_table_lookup_prefetch_size','_table_lookup_prefetch_thresh','_multi_join_key_table_lookup')
9
NAME VALUE SES_M SYS_MODIF DESCRIPTION
-------------------------------------------------- -------------------- ----- --------- ------------------------------------------------------------
_table_lookup_prefetch_size 40 false false table lookup prefetch vector size
_multi_join_key_table_lookup TRUE false false TRUE iff multi-join-key table lookup prefetch is enabled
_table_lookup_prefetch_thresh 2 false false table lookup prefetch threshold
SQL>
\-데이터 정렬 시 pga 안의 sort area 를 이용한다
\-sort 공간 부족 시 temp tablespace 이용하는데
정렬 된 데이터를 temp tablespace 에 쓰고 읽을 때 direct path i/o 방식 사용한다
\-병렬 쿼리로 full scan 수행 시 발생
\-수행 전 연관 세그먼트에 대해 버퍼 - 파일 간 동기화 수행하여 dirty buffer 를 없엠
버퍼의 내용이 파일에 기록되지 않은 상태에서 파일을 직접 읽으면 정합성에 문제
A 노드는 마스터인 B 노드에 전송 요청 - gc cr request
B 노드는 어떤 노드에도 K 를 캐싱하지 않음을 확인하고 A 노드에 직접 Scur 로 읽도록 권한 부여
A 노드는 디스크에서 읽어 로컬캐싱
C 는 MASTER 인 B 에 K 전송요청 - gc cr request
B 는 K 를 A 가 캐싱하므로 C 에 k 를 주도록 A 에 지시
A 는 C 에 전송, C 는 받아서 Scur 캐싱하고 B 에 완료 메시지 보냄
A 가 마스터 B 에게 k 를 xcur 로 요청
B 는 k 를 C 가 Xcur 로 캐싱 학인, A 에게 전송 지시
C 는 A 에게 전송, 가진 블록은 null 로 다운(c 의 xcur 은 커밋되지 않아 rowlock 상태일 수도 있다)
A 는 k 를 Xcur 로 갱신했음을 B 에게 알림
\--> 다른 인스턴스가 생신중인 블록을 읽을 때 row lock 이 해소되기 전에도 블록을 주고받는다
\--> 쓰기 쓰기 상황이라도 Disk 에 기록 없이 바로 다른 Instance 에 전송한다(디스크 동기화 없이 진행)
A 가 xcur 로 다시 갱신했으므로 k scn 은 154 \--> 168
C 는 B 에게 k 를 sCur 로 요청
B 는 k 를 A 가 Xcur 로 캐싱 확인 후 C 에게 전송 지시
A 는 C 에게 블록 전송, 자신의 블록은 Scur 로 다운
A 에서 Commit 되지 않았을 경우 Current 가 아닌 Cr Copy 를 만들어 전송
--> C 는 읽기만 하므로 Current 를 보낼 필요까지는 없다
--> Current 를 보내면 언젠가 다시 가져와야 하므로 부담스럽다
A 에서 Commit 되더라도 바로 Current 블록을 보내지 않는다
--> 처음에는 Cr Copy 만 전송하다 일정 횟수 이상 반복 요청이 오면 Current 를 보냄
--> Current 를 보내려면 자신의 xCur 을 sCur 로 다운해야 하는데 곧이어 갱신이 필요한 상황이면 다시 xCur 로 업그레이드 해야 하기 때문
--> 그때는 sCur 을 가져간 다른 노드도 모두 null 로 다운해야 하므로 RAC 부하 증가
--> Cr Copy 를 보내는 횟수는 _fairness_threshold 에 의해 결정(10g defAult = 4, 11g 는 2)
--> 값에 도달하면 redo 버퍼를 비우고 Xcur 을 Scur 로 다운,
Scur 이므로 이후에 읽기 요청하는 노드는 Cr Copy 가 아니라 Scur 로 전송받음
아래 쿼리의 downgrade ratio 가 높다면 current 로 공유할 수 밖에 없음에도 cr 을 만들어 보내주느라 비효율적 작업을 함을 의미
SQL> select
data_requests, fairness_down_converts
, round (fairness_down_converts / data_requests * 100) "DOWNGRADE RATIO(%)"
from v$cr_block_server;
DATA_REQUES FAIRNESS_DO DOWNGRADE R
----------- ----------- -----------
136788509 83742131 61
1 rows selected.
RAC 캐시퓨전 부하도 I/O 부하와 같은 맥락이다
블록의 읽기 요청이 많으면 I/O 이벤트 증가, RAC 관련 이벤트 증가
SQL 튜닝을 통해 블록 읽기 요청 횟수를 줄여 인터커넥트 전송량을 감소시켜야 한다
11g 에서 제공하는 result cache 기능은
SQL> select /*+ result_cache */ object_name from test1;
SQL> select
CREATION_TIMESTAMP
,ID
,TYPE
,STATUS
,NAME
,NAMESPACE
,BLOCK_COUNT
,CACHE_ID
from V$RESULT_CACHE_OBJECTS
ORDER BY CREATION_TIMESTAMP;
CREATION_TIMESTAMP ID TYPE STATUS NAME NAMES BLOCK_COUNT CACHE_ID
------------------- ----------- ---------- --------- -------------------------------------------------------------------------------------------------------------------------------- ----- ----------- ---------------------------------------------------------------------------------------------
2016/04/30 07:39:20 0 Dependency Published OPS$ORACLE.TEST1 1 OPS$ORACLE.TEST1
2016/04/30 07:39:20 1 Result Invalid select /*+ RESULT_CACHE */ * from test1 SQL 9 7dw9mfrbc4sckb8u8ubc9fswk1
2016/04/30 07:39:46 10 Result Invalid select /*+ result_cache */ object_name from test1 SQL 2 3ndv1c9p6scrv33mxya0cyknzg
2016/04/30 07:40:04 12 Result Invalid select /*+ result_cache */ object_name from test1 SQL 2 3ndv1c9p6scrv33mxya0cyknzg
2016/04/30 07:40:10 14 Result Invalid select /*+ result_cache */ object_name from test1 SQL 2 3ndv1c9p6scrv33mxya0cyknzg
2016/04/30 07:41:47 16 Result Bypass select /*+ result_cache */ object_name from test1 SQL 2 3ndv1c9p6scrv33mxya0cyknzg
6 rows selected.
select /*+ result_cache */ col1, col2 from table;
create or replace function test_fnc (in_num number)
return varchar2
RESUTL_CACHE RELIES_ON(cache_table)
is
..
-서버 프로세스는 result cache 메모리를 먼저 찾아보고 캐싱되지 않으면 쿼리 수행 후 캐시에 저장
-SQL Query result cache
-PL/SQL function result cache
Where 조건절의 서브쿼리 캐싱은 불가능하다
쿼리 튜닝 예시는 책 참조
1. 전략적 인덱스 구성
2. DBMS 제공하는 기능 활용
파티션, 클러스터, IOT 등...
3. 옵티마이저 모드 설정
all_rows, first_rows
4. 통계정보 생성
아래 항목들이 통계정보로 수집 가능하다
CPU
평균 Single block, Multi block I/O 속도
평균 Multi block I/O 수
5. 필요 시 힌트를 적극적으로 사용한다