테이블 전체 건수를 조회하는 방법을 살펴보자.
테스트를 위해 아래와 같이 테이블과 인덱스를 생성하자. c1 칼럼은 NOT NULL 제약 조건으로 생성했다. t1_x1 인덱스는 NOT NULL 제약 조건 칼럼이 포함되어 있고, t1_x2 인덱스는 그러지 않다.
-- 1 DROP TABLE t1 PURGE; CREATE TABLE t1 (c1 NOT NULL, c2, c3) AS SELECT LPAD ('X', 10, 'X') AS c1 , LPAD ('X', 10, 'X') AS c2 , LPAD ('X', 100, 'X') AS c3 FROM XMLTABLE ('1 to 100000'); CREATE INDEX t1_x1 ON t1 (c1, c2); CREATE INDEX t1_x2 ON t1 (c2);
아래 쿼리는 COUNT (*) 표현식을 사용했다. NOT NULL 칼럼이 포함된 인덱스가 존재하는 경우 크기가 가장 작은 인덱스를 사용하는 실행 계획이 수립된다. t1_x2 인덱스는 t1_x1 인덱스보다 크기가 작지만 널 값을 포함하지 않으므로 테이블 전체 건수를 조회하는데 사용할 수 없다.
-- 2-1 SELECT COUNT (*) FROM t1; --------------------------------------- | Id | Operation | Name | --------------------------------------- | 0 | SELECT STATEMENT | | | 1 | SORT AGGREGATE | | | 2 | INDEX FAST FULL SCAN| T1_X1 | ---------------------------------------
대용량 테이블인 경우 INDEX_FFS 힌트와 PARALLEL_INDEX 힌트를 사용하면 테이블 전체 건수를 빠르게 조회할 수 있다.
-- 2-2 SELECT /*+ INDEX_FFS(T1) PARALLEL_INDEX(T1 4) */ COUNT (*) FROM t1; ---------------------------------------------- | Id | Operation | Name | ---------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | SORT AGGREGATE | | | 2 | PX COORDINATOR | | | 3 | PX SEND QC (RANDOM) | :TQ10000 | | 4 | SORT AGGREGATE | | | 5 | PX BLOCK ITERATOR | | |* 6 | INDEX FAST FULL SCAN| T1_X1 | ----------------------------------------------
t1_x1 인덱스를 삭제해보자.
-- 3 DROP INDEX t1_x1; 인덱스가 삭제되었습니다.
2-1번 쿼리를 다시 수행해보면 테이블을 FULL SCAN하는 것을 확인할 수 있다. 사용할 수 있는 인덱스가 없기 때문이다.
-- 4-1 SELECT COUNT (*) FROM t1; ----------------------------------- | Id | Operation | Name | ----------------------------------- | 0 | SELECT STATEMENT | | | 1 | SORT AGGREGATE | | | 2 | TABLE ACCESS FULL| T1 | -----------------------------------
이런 경우에는 FULL 힌트와 PARALLEL 힌트를 사용해야 한다.
-- 4-2 SELECT /*+ FULL(T1) PARALLEL(T1 4) */ COUNT (*) FROM t1; ------------------------------------------- | Id | Operation | Name | ------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | SORT AGGREGATE | | | 2 | PX COORDINATOR | | | 3 | PX SEND QC (RANDOM) | :TQ10000 | | 4 | SORT AGGREGATE | | | 5 | PX BLOCK ITERATOR | | |* 6 | TABLE ACCESS FULL| T1 | -------------------------------------------
NOT NULL 칼럼이 포함된 인덱스의 존재 여부에 따라 힌트를 달리 기술하는 것은 번거로운 일이다. 이런 경우 아래와 같은 힌트를 사용할 수 있다. 모순되는 힌트지만 특수한 경우로 이해하자.
-- 5 SELECT /*+ INDEX_FFS(T1) PARALLEL_INDEX(T1 4) FULL(T1) PARALLEL(T1 4) */ COUNT (*) FROM t1; ------------------------------------------- | Id | Operation | Name | ------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | SORT AGGREGATE | | | 2 | PX COORDINATOR | | | 3 | PX SEND QC (RANDOM) | :TQ10000 | | 4 | SORT AGGREGATE | | | 5 | PX BLOCK ITERATOR | | |* 6 | TABLE ACCESS FULL| T1 | -------------------------------------------
t1_x1 인덱스를 다시 생성해보자.
-- 6 CREATE INDEX t1_x1 ON t1 (c1, c2); 인덱스가 생성되었습니다.
쿼리를 다시 수행하면 T1_X1 인덱스를 FFS하는 것을 확인할 수 있다.
-- 7 SELECT /*+ INDEX_FFS(T1) PARALLEL_INDEX(T1 4) FULL(T1) PARALLEL(T1 4) */ COUNT (*) FROM t1; ---------------------------------------------- | Id | Operation | Name | ---------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | SORT AGGREGATE | | | 2 | PX COORDINATOR | | | 3 | PX SEND QC (RANDOM) | :TQ10000 | | 4 | SORT AGGREGATE | | | 5 | PX BLOCK ITERATOR | | |* 6 | INDEX FAST FULL SCAN| T1_X1 | ----------------------------------------------
'Oracle > Tuning' 카테고리의 다른 글
중복 조회로 랜덤 I/O를 감소시키는 튜닝 기법 (0) | 2019.04.24 |
---|---|
바인드 변수 크기에 따른 커서 생성 (0) | 2019.04.23 |
TIMESTAMP 인덱스 - Right-Growing 경합 #2 (0) | 2019.03.06 |
TIMESTAMP 인덱스 - Right-Growing 경합 #1 (0) | 2019.02.28 |
CLOB #6 - 블록 I/O (0) | 2019.02.27 |