Oracle/Tuning2012. 6. 28. 11:40

조금 특이한 유형의 부분 범위 처리 사례를 살펴보자.

 

테스트를 위해 아래와 같이 테이블을 생성하자.

-- 1
DROP TABLE t1 PURGE;

CREATE TABLE t1 AS
SELECT DATE '2012-01-01' + ROWNUM - 1 AS c1, ROWNUM AS c2 FROM XMLTABLE ('1 to 365');

CREATE INDEX t1_x1 ON t1 (c1);

 

아래 쿼리는 v1 변수에 -1을 입력하면 전체 행을 반환된다. ROWNUM 슈도 칼럼끼리 비교했기 때문에 부분 범위 처리가 동작하지 않는다.

VAR v1 NUMBER;
EXEC :v1 := 10;

-- 2
SELECT a.*, ROWNUM AS rn
  FROM (SELECT   a.*
            FROM t1 a
           WHERE a.c1 <= DATE '2012-06-30'
        ORDER BY a.c1 DESC) a
 WHERE ROWNUM <= DECODE (:v1, -1, ROWNUM, :v1);

----------------------------------------------------------
| Id  | Operation                       | Name  | A-Rows |
----------------------------------------------------------
|   0 | SELECT STATEMENT                |       |     10 |
|   1 |  COUNT                          |       |     10 |
|*  2 |   FILTER                        |       |     10 |
|   3 |    VIEW                         |       |    182 |
|   4 |     TABLE ACCESS BY INDEX ROWID | T1    |    182 |
|*  5 |      INDEX RANGE SCAN DESCENDING| T1_X1 |    182 |
----------------------------------------------------------


아래 쿼리는 ROWNUM 슈도 칼럼 대신 충분히 큰 숫자(1e9)를 기술했다. 실행 계획에서 부분 범위 처리가 동작하는 것을 확인할 수 있다.

--3
SELECT a.*, ROWNUM AS rn
  FROM (SELECT   a.*
            FROM t1 a
           WHERE a.c1 <= DATE '2012-06-30'
        ORDER BY a.c1 DESC) a
 WHERE ROWNUM <= DECODE (:v1, -1, 1e9, :v1);

---------------------------------------------------------
| Id  | Operation                      | Name  | A-Rows |
---------------------------------------------------------
|   0 | SELECT STATEMENT               |       |     10 |
|*  1 |  COUNT STOPKEY                 |       |     10 |
|   2 |   VIEW                         |       |     10 |
|   3 |    TABLE ACCESS BY INDEX ROWID | T1    |     10 |
|*  4 |     INDEX RANGE SCAN DESCENDING| T1_X1 |     10 |
---------------------------------------------------------


Posted by 정희락_