ORDER BY 절에 지정한 정렬 조건에 따라 인덱스로 소트를 회피할 수 없는 경우가 있다.
테스트를 위해 아래와 같이 데이터를 생성하자.
-- 1 DROP TABLE t1 PURGE; CREATE TABLE t1 AS SELECT DATE '2050-01-01' + ROWNUM - 1 AS c1, 'X' AS c2 FROM XMLTABLE ('1 to 31'); CREATE INDEX t1_X1 ON t1 (c1);
아래 쿼리는 인덱스에 의해 소트가 제거된다.
-- 2 SELECT * FROM t1 WHERE c1 >= DATE '2050-01-01' ORDER BY c1; --------------------------------------------- | Id | Operation | Name | --------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | |* 2 | INDEX RANGE SCAN | T1_X1 | ---------------------------------------------
아래 쿼리는 ORDER BY 절의 열이 가공되었기 때문에 소트가 발생한다.
-- 3 SELECT * FROM t1 WHERE c1 >= DATE '2050-01-01' ORDER BY TO_CHAR (c1, 'YYYYMMDD'); ------------------------------------------------------ | Id | Operation | Name | ------------------------------------------------------ | 0 | SELECT STATEMENT | | | 1 | SORT ORDER BY | | | 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | |* 3 | INDEX RANGE SCAN | T1_X1 | ------------------------------------------------------
아래 쿼리도 소트가 발생한다. Alias가 우선되기 때문에 TO_CHAR (c1, 'YYYYMMDD')로 정렬되었다.
-- 4 SELECT TO_CHAR (c1, 'YYYYMMDD') AS c1, c2 FROM t1 WHERE c1 >= DATE '2050-01-01' ORDER BY c1; ------------------------------------------------------ | Id | Operation | Name | ------------------------------------------------------ | 0 | SELECT STATEMENT | | | 1 | SORT ORDER BY | | | 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | |* 3 | INDEX RANGE SCAN | T1_X1 | ------------------------------------------------------
아래 쿼리도 소트가 발생한다. ORDER BY 절에 열 위치를 지정하면 열 위치가 SELECT 절의 표현식으로 대체되기 때문이다.
-- 5 SELECT TO_CHAR (c1, 'YYYYMMDD') AS c1, c2 FROM t1 WHERE c1 >= DATE '2050-01-01' ORDER BY 1; ------------------------------------------------------ | Id | Operation | Name | ------------------------------------------------------ | 0 | SELECT STATEMENT | | | 1 | SORT ORDER BY | | | 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | |* 3 | INDEX RANGE SCAN | T1_X1 | ------------------------------------------------------
해법은 간단하다. ORDER BY 절의 열을 테이블이나 Alias로 한정해주면 된다.
-- 6 SELECT TO_CHAR (c1, 'YYYYMMDD') AS c1, c2 FROM t1 WHERE c1 >= DATE '2050-01-01' ORDER BY t1.c1; --------------------------------------------- | Id | Operation | Name | --------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | TABLE ACCESS BY INDEX ROWID| T1 | |* 2 | INDEX RANGE SCAN | T1_X1 | ---------------------------------------------
'Oracle > Tuning' 카테고리의 다른 글
소트 #3 - IN 절 (0) | 2018.03.04 |
---|---|
소트 #2 - 조인 정렬 조건 (0) | 2018.03.04 |
블록 그래뉼과 파티션 그래뉼 (0) | 2018.03.03 |
PQ_REPLICATE 힌트 (1) | 2018.03.03 |
Nonprefix 로컬 인덱스와 소트 #2 (1) | 2018.03.02 |