ROWNUM이 존재하게 되면 오라클의 특성 상 ROWNUM이 존재하는 집합을 먼저 만들고 인라인 뷰 밖의 조건(DEPTNO 조인키)을 필터시키기 때문에 문제가 된다.
문제가 되는 이유는 EMP 테이블에 천만건의 데이터가 있는데 이 천만건을 모두 액세스한 뒤 9건밖에 존재하지 않는 'DEPTNO = 10' 데이터를 필터링 시키기 때문이며, 실행계획에서도 이러한 문제를 Id 3번를 보면 access가 아닌 filter로 처리된다는 것을 확인할 수 있다.
ALTER SESSION SET STATISTICS_LEVEL = ALL; SELECT EMP_V.* FROM (SELECT ROWNUM, EMPNO, JOB, HIREDATE, DEPTNO FROM EMP) EMP_V, DEPT D WHERE EMP_V.DEPTNO = D.DEPTNO AND D.DEPTNO = 10; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST')); --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | --------------------------------------------------------------------------------------------------- | 1 | NESTED LOOPS | | 1 | 9991K| 9 |00:00:25.47 | 44243 | 7482 | |* 2 | INDEX UNIQUE SCAN | DEPT_U1 | 1 | 1 | 1 |00:00:00.01 | 1 | 0 | |* 3 | VIEW | | 1 | 9991K| 9 |00:00:25.47 | 44242 | 7482 | | 4 | COUNT | | 1 | | 10M|00:00:10.00 | 44242 | 7482 | | 5 | TABLE ACCESS FULL| EMP | 1 | 9991K| 10M|00:00:10.00 | 44242 | 7482 | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("D"."DEPTNO"=10) 3 - filter("EMP_V"."DEPTNO"=10)
튜닝 후
이를 해결하기 위해서는 결국 문제가 되는 ROWNUM을 인라인 뷰 밖으로 가져오면 되며, 실제 그렇게 변경할 경우 아래처럼 조인조건이 인라인 뷰 안으로 침투가 되어 인덱스를 사용하는 것을 확인할 수 있다.
SELECT ROWNUM, EMP_V.* FROM (SELECT EMPNO, JOB, HIREDATE, DEPTNO FROM EMP) EMP_V, DEPT D WHERE EMP_V.DEPTNO = D.DEPTNO AND D.DEPTNO = 10; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST')); --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | --------------------------------------------------------------------------------------------------- | 1 | COUNT | | 1 | | 9 |00:00:00.01 | 7 | | 2 | NESTED LOOPS | | 1 | 1 | 9 |00:00:00.01 | 7 | |* 3 | INDEX UNIQUE SCAN | DEPT_U1 | 1 | 1 | 1 |00:00:00.01 | 1 | | 4 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 1 | 9 |00:00:00.01 | 6 | |* 5 | INDEX RANGE SCAN | EMP_N1 | 1 | 1 | 9 |00:00:00.01 | 4 | --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("D"."DEPTNO"=10) 5 - access("DEPTNO"=10)
'ORACLE > 튜닝' 카테고리의 다른 글
SPM(SQL PLAN MANAGEMENT) 사용 방법 #2 (0) | 2017.06.15 |
---|---|
SPM(SQL PLAN MANAGEMENT) 사용 방법 #1 (0) | 2017.06.15 |
SQL 튜닝 - Query Block Name 사용 (0) | 2017.06.15 |
SQL 튜닝- 조건절 OR 사용시.. (Predicate , Query Block Name) (0) | 2017.06.15 |
DBMS_XPLAN.DISPLAY_CURSOR 사용방법 (0) | 2017.06.15 |