오라클 성능 고도화 원리와 해법 II (2016년)
공통 표현식 제거 0 0 4,075

by 구루비 쿼리변환 공통표현식제거 [2017.05.25]


08. 공통 표현식 제거

같은 조건식이 여러 곳에서 반복 사용될 경우, 오라클은 해당 조건식이 각 로우당 한 번씩만 평가되도록 쿼리를 변환하는데, 이를 '공통 표현식 제거'라고 한다.

_eliminate_common_subexpr 파라미터를 통해 제어한다.


select /*+ no_expand */ * from emp e, dept d
where (e.deptno = d.deptno and e.job = 'CLERK' and d.loc = 'DALLAS')
      or
      (e.deptno = d.deptno and e.job = 'CLERK' and e.sal >= 1000)


select * from emp e, dept d
where e.deptno = d.deptno
and   e.job = 'CLERK'
and  (d.loc = 'DALLAS' or e.sal >= 1000)


create index emp_job_idx on emp(job);

select * from emp e, dept d                                                                  
where (e.deptno = d.deptno and e.job = 'CLERK' and d.loc = 'DALLAS')                                
or    (e.deptno = d.deptno and e.job = 'CLERK' and e.sal >=1000);                                    
                                                                                              
                                                                                             
--------------------------------------------------------------------
| Id  | Operation                    | Name        | Rows  | Bytes |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |     3 |   150 |
|   1 |  NESTED LOOPS                |             |     3 |   150 |
|   2 |   TABLE ACCESS BY INDEX ROWID| EMP         |     3 |    96 |
|*  3 |    INDEX RANGE SCAN          | EMP_JOB_IDX |     3 |       |
|*  4 |   TABLE ACCESS BY INDEX ROWID| DEPT        |     1 |    18 |
|*  5 |    INDEX UNIQUE SCAN         | DEPT_PK     |     1 |       |
--------------------------------------------------------------------
                                                                                              
Predicate Information (identified by operation id):                                           
---------------------------------------------------                                           
   3 - access("E"."JOB"='CLERK')   
   4 - filter("D"."LOC"='DALLAS' OR "E"."SAL">=1000)                                          
   5 - access("E"."DEPTNO"="D"."DEPTNO")  

OR-Expansion 쿼리 변환을 수행


alter session set "_eliminate_common_subexpr" = false;

select * from emp e, dept d
where (e.deptno = d.deptno and e.job = 'CLERK' and d.loc = 'DALLAS')
       or 
      (e.deptno = d.deptno and e.job = 'CLERK' and e.sal >= 1000)


---------------------------------------------------------------------
| Id  | Operation                     | Name        | Rows  | Bytes |
---------------------------------------------------------------------
|   0 | SELECT STATEMENT              |             |     4 |   200 |
|   1 |  CONCATENATION                |             |       |       |
|   2 |   NESTED LOOPS                |             |     3 |   150 |
|*  3 |    TABLE ACCESS BY INDEX ROWID| EMP         |     3 |    96 |
|*  4 |     INDEX RANGE SCAN          | EMP_JOB_IDX |     3 |       |
|   5 |    TABLE ACCESS BY INDEX ROWID| DEPT        |     1 |    18 |
|*  6 |     INDEX UNIQUE SCAN         | DEPT_PK     |     1 |       |
|   7 |   NESTED LOOPS                |             |     1 |    50 |
|   8 |    TABLE ACCESS BY INDEX ROWID| EMP         |     3 |    96 |
|*  9 |     INDEX RANGE SCAN          | EMP_JOB_IDX |     3 |       |
|* 10 |    TABLE ACCESS BY INDEX ROWID| DEPT        |     1 |    18 |
|* 11 |     INDEX UNIQUE SCAN         | DEPT_PK     |     1 |       |
---------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter("E"."SAL">=1000)
   4 - access("E"."JOB"='CLERK')
   6 - access("E"."DEPTNO"="D"."DEPTNO")
   8 - filter(LNNVL("E"."SAL">=1000))   -> 위아래 집합 간 중복 제거
   9 - access("E"."JOB"='CLERK')
  10 - filter("D"."LOC"='DALLAS')
  11 - access("E"."DEPTNO"="D"."DEPTNO")
  

FULL SCAN

  
select /*+ NO_EXPAND */ * from emp e, dept d
where (e.deptno = d.deptno and e.job = 'CLERK' and d.loc = 'DALLAS')
       or 
      (e.deptno = d.deptno and e.job = 'CLERK' and e.sal >= 1000)
  

----------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)|
----------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     5 |   285 |     8   (0)|
|   1 |  NESTED LOOPS      |      |     5 |   285 |     8   (0)|
|   2 |   TABLE ACCESS FULL| DEPT |     4 |    80 |     3   (0)|
|   3 |   TABLE ACCESS FULL| EMP  |     1 |    37 |     1   (0)|
---------------------------------------------------------------- 

"구루비 주주클럽 스터디모임" 에서 2016년에 "오라클 성능 고도화 원리와 해법 II " 도서를 스터디하면서 정리한 내용 입니다.

- 강좌 URL : http://www.gurubee.net/lecture/3364

- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입