call count cpu elapsed disk query current rows
------ ----- ----- ------- ---- ----- ------ ----
Parse 15 0.00 0.08 0 0 0 0
Execute 44 0.03 0.03 0 0 0 0
Fetch 44 0.01 0.13 18 822 0 44
------ ----- ----- ------- ---- ----- ------ ----
total 103 0.04 0.25 18 822 0 44
}* 대용량의 데이터를 읽고 쓰는 데 다양한 네트워크 기술(NAS, SAN)이 사용됨에 따라 네트워크 속도도 SQL 성능에 크게 양향을 미침
\\ {code:sql}selectcount(*)fromtwhereowner like 'SYS%' Rows Row Source Operation ----- ------------------------------ 1 SORT AGGREGATE (cr=691 pr=0 pw=0 time=13037 us) 24613 TABLE ACCESS FULL T (cr=691 pr=0 pw=0 time=98473 us)
- 전체 레코드 49,906건
- 선택 레코드 1건 (0.002 %)
- 읽은 블록수 691 블록
- Table Full Scan 비효율 발생
\\ {code:sql}create index t_idx on t(owner, object_name);select/*+ index(t t_idx) */ count(*)fromtwhereowner like 'SYS%' and object_name = 'ALL_OBJECTS' Rows Row Source Operation ---- ------------------------------ 1 SORT AGGREGATE (cr=76 pr=0 pw=0 time=7009 us) 1 INDEX RANGE SCAN T_IDX (cr=76 pr=0 pw=0 time=6972 us)(Object ID 55337)
- 인덱스 순서를 변경해줌으로써 루트와 리프 단 2개의 인덱스 블록만 읽어 가장 효율적인 방식으로 Sequential 액세스 수행
- 인덱스로부터 만족하는 22,934건을 읽어 그 횟수만큼 테이블을 Random 액세스수행하여 최종적으로 1건의 결과 추출
- 최종 선택된 것에 비해 너무 많은 Random 액세스 발생
\\ {code:sql}drop index t_idx; create index t_idx on t(owner, object_name);selectobject_idfromtwhereowner = 'SYS' and object_name = 'ALL_OBJECTS' Rows Row Source Operation ---- ------------------------------ 1 TABLE ACCESSBYINDEX ROWID T (cr=4 pr=0 pw=0 time=67 us) 1 INDEX RANGE SCAN T_IDX (cr=3 pr=0 pw=0 time=51 us)(Object ID 55340)
\- Single Block I/O : 한번의 I/O Call에 하나의 데이터 블록만 읽어서 메모리에 적재하는 방식
\-인덱스를 통해 테이블을 엑세스할때, 기본적으로 인덱스와 테이블 모두 이 방식 사용
Single Block I/O 방식
create table t asselect*fromall_objects; alter table t add constraint t_pk primary key(object_id);select/*+ index(t) */ count(*)fromtwhereobject_id > 0 call count cpu elapsed disk query current rows ----- ---- ---- ------ ---- ----- ----- ------ Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.26 0.25 64 65 0 1 ----- ---- ---- ------ ---- ----- ----- ------ total 4 0.26 0.25 64 65 0 1 Rows Row Source Operation ----- ------------------------------ 1 SORT AGGREGATE (cr=65 r=64 w=0 time=256400 us) 31192 INDEX RANGE SCAN T_PK (cr=65 r=64 w=0 time=134613 us) Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ------------------------------- Waited --------- ------------ SQL*Net message to client 2 0.00 0.00 db file sequential read 64 0.00 0.00 SQL*Net messagefromclient 2 0.05 0.05
MultiBlock I/O 방식
-- 디스크 I/O가 발생하도록 버퍼 캐시 Flushing alter system flush buffer_cache; -- Multiblock I/O 방식으로 인덱스 스캔 select /*+ index_ffs(t) */ count(*) from t where object_id > 0 call count cpu elapsed disk query current rows ----- ----- ---- ------- ---- ----- ------- ---- Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.26 0.26 64 69 0 1 ----- ----- ---- ------- ---- ----- ------- ---- total 4 0.26 0.26 64 69 0 1 Rows Row Source Operation ----- ------------------------------ 1 SORT AGGREGATE (cr=69 r=64 w=0 time=267453 us) 31192 INDEX FAST FULL SCAN T_PK (cr=69 r=64 w=0 time=143781 us) Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ------------------------------ Waited --------- ------------ SQL*Net message to client 2 0.00 0.00 db file scattered read 9 0.00 0.00 SQL*Net message from client 2 0.35 0.36
\\ {code:sql}select카드번호 , sum( case when 거래일자 = to_char(sysdate-1,'yyyymmdd') then 거래금액 end ) 전일_거래금액 , sum( case when 거래일자 between to_char(sysdate-7,'yyyymmdd') and to_char(sysdate-1,'yyyymmdd') then 거래금액 end ) 주간_거래금액 , sum( case when 거래일자 between to_char(add_months(sysdate,-1),'yyyymm') || '01' and to_char(last_day(add_months(sysdate,-1)),'yyyymmdd') then 거래금액 end ) 전월_거래금액 , sum( 거래금액 )연중_거래금액from일별카드거래내역where거래일자 between to_char(add_months(sysdate,-12),'yyyymmdd') and to_char(sysdate-1,'yyyymmdd')groupby카드번호havingsum( case when 거래일자 = to_char(sysdate-1,'yyyymmdd') then 거래금액 end ) > 0
\- 최적의 옵티마이징 팩터를 제공했다면 가급적 옵티마이저에게 맡기는것이 바람직하지만, 옵티마이저가 생각만큼 최적의 실행계획을 수립하지 못하는경우 사용
예시)
[예제] Oracle select /*+ leading(d) use_nl(e) index(d dept_loc_idx) */ * from emp e, dept d where e.deptno = d.deptno and d.loc = 'CHICAGO' [예제] SQL Server select * from dept d with (index(dept_loc_idx)), emp e where e.deptno = d.deptno and d.loc = 'CHICAGO' option (force order, loop join)