-Intersect 나 Minus 같은 집합 연산을 조인 형태로 변환하는 것을 말함
_________________________________________________________________________________________________________________
TEST
-deptno=10에 속한 사원들의 job,mgr을 제외시키고 나머지 job,mgr 집합만을 찾는 쿼리
|
SQL> set autotrace traceonly exp; SQL> select job, mgr from emp 2 minus 3 select job, mgr from emp 4 where deptno = 10 ;
Execution Plan ----------------------------------------------------------
----------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ----------------------------------------------------------------- | 0 | SELECT STATEMENT | | 15 | 225 | 8 (63)| | 1 | MINUS | | | | | | 2 | SORT UNIQUE | | 15 | 180 | 4 (25)| | 3 | TABLE ACCESS FULL| EMP | 15 | 180 | 3 (0)| | 4 | SORT UNIQUE | | 3 | 45 | 4 (25)| |* 5 | TABLE ACCESS FULL| EMP | 3 | 45 | 3 (0)| -----------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
5 - filter("DEPTNO"=10) |
*각각 sort unique 연산을 수행한 후에 Minus연산을 수행
-_convert_set_to_join 파라미터를 true로 설정
|
SQL> alter session set "_convert_set_to_join" = true;
세션이 변경되었습니다.
SQL> select job, mgr from emp 2 minus 3 select job, mgr from emp 4 where deptno = 10 ;
Execution Plan ----------------------------------------------------------
----------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ----------------------------------------------------------------- | 0 | SELECT STATEMENT | | 11 | 297 | 8 (25)| | 1 | HASH UNIQUE | | 11 | 297 | 8 (25)| |* 2 | HASH JOIN ANTI | | 11 | 297 | 7 (15)| | 3 | TABLE ACCESS FULL| EMP | 15 | 180 | 3 (0)| |* 4 | TABLE ACCESS FULL| EMP | 3 | 45 | 3 (0)| -----------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
2 - access(SYS_OP_MAP_NONNULL("JOB")=SYS_OP_MAP_NONNULL("JOB") AND SYS_OP_MAP_NONNULL("MGR")=SYS_OP_MAP_NONNULL("MGR")) 4 - filter("DEPTNO"=10) |
*해시 anti 조인을 수행하고 나서 중복 값을 제거하기 위한 hash unique 연산을 수행
-다음과 같은 쿼리 변환이 일어남
|
SQL> select distinct job, mgr from emp e 2 where not exists ( 3 select 'x' from emp 4 where deptno = 10 5 and sys_op_map_nonnull(job) = sys_op_map_nonnull(e.job) 6 and sys_op_map_nonnull(mgr) = sys_op_map_nonnull(e.mgr) 7 ) ;
Execution Plan ----------------------------------------------------------
----------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ----------------------------------------------------------------- | 0 | SELECT STATEMENT | | 11 | 297 | 8 (25)| | 1 | HASH UNIQUE | | 11 | 297 | 8 (25)| |* 2 | HASH JOIN ANTI | | 11 | 297 | 7 (15)| | 3 | TABLE ACCESS FULL| EMP | 15 | 180 | 3 (0)| |* 4 | TABLE ACCESS FULL| EMP | 3 | 45 | 3 (0)| -----------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
2 - access(SYS_OP_MAP_NONNULL("JOB")=SYS_OP_MAP_NONNULL("E"."JOB") AND SYS_OP_MAP_NONNULL("MGR")=SYS_OP_MAP_NONNULL("E"."MGR")) 4 - filter("DEPTNO"=10) |
*sys_op_map_nonnull
null 값끼리 비교(null=null)하면 false이지만 가끔 true가 되도록 처리해야 하는 경우가 있고 그럴 때 위 함수를 사용
위에서는 job과 mgr이 null 허용 컬럼이기 때문에 위와 같은 처리가 일어난다