NOT EXISTS 서브 쿼리의 SELECT 절에 메인 쿼리의 열을 기술하면 서브 쿼리가 UNNEST되지 않는다.
테스트를 위해 아래와 같이 테이블을 생성하자.
1 2 3 4 5 6 |
-- 1 DROP TABLE t1 PURGE; DROP TABLE t2 PURGE; CREATE TABLE t1 AS SELECT ROWNUM AS c1, ROWNUM AS c2 FROM XMLTABLE ( '1 to 10000' ); CREATE TABLE t2 AS SELECT * FROM t1; |
2-1번 쿼리는 NOT EXISTS 서브 쿼리의 SELECT 절에 메인 쿼리의 열(a.c1)을 기술했다. 서브 쿼리가 UNNEST되지 못하고 필터 방식으로 처리되는 것을 확인할 수 있다. 이런 경우 쿼리의 성능이 저하될 수 있다. 2-2번 쿼리처럼 리터럴(1)을 기술하면 서브 쿼리가 UNNEST되어 안티 조인 방식으로 조인된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
-- 2-1 SELECT * FROM t1 a WHERE NOT EXISTS ( SELECT /*+ UNNEST HASH_AJ */ a.c1 -- ! FROM t2 x WHERE x.c1 = a.c1); ----------------------------------- | Id | Operation | Name | ----------------------------------- | 0 | SELECT STATEMENT | | |* 1 | FILTER | | | 2 | TABLE ACCESS FULL | T1 | |* 3 | TABLE ACCESS FULL | T2 | ----------------------------------- -- 2-2 SELECT * FROM t1 a WHERE NOT EXISTS ( SELECT 1 FROM t2 x WHERE x.c1 = a.c1); ------------------------------------- | Id | Operation | Name | ------------------------------------- | 0 | SELECT STATEMENT | | |* 1 | HASH JOIN RIGHT ANTI| | | 2 | TABLE ACCESS FULL | T2 | | 3 | TABLE ACCESS FULL | T1 | ------------------------------------- |
EXISTS 서브 쿼리는 SELECT 절에 메인 쿼리의 열을 기술해도 세미 조인 방식으로 조인된다. 하지만 3-2번 쿼리처럼 리터럴을 기술하는 편이 바람직하다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
-- 3-1 SELECT * FROM t1 a WHERE EXISTS ( SELECT a.c1 -- ! FROM t2 x WHERE x.c1 = a.c1); ------------------------------------- | Id | Operation | Name | ------------------------------------- | 0 | SELECT STATEMENT | | |* 1 | HASH JOIN RIGHT SEMI| | | 2 | TABLE ACCESS FULL | T2 | | 3 | TABLE ACCESS FULL | T1 | ------------------------------------- -- 3-2 SELECT * FROM t1 a WHERE EXISTS ( SELECT 1 FROM t2 x WHERE x.c1 = a.c1); ------------------------------------- | Id | Operation | Name | ------------------------------------- | 0 | SELECT STATEMENT | | |* 1 | HASH JOIN RIGHT SEMI| | | 2 | TABLE ACCESS FULL | T2 | | 3 | TABLE ACCESS FULL | T1 | ------------------------------------- |
'Oracle > Tuning' 카테고리의 다른 글
월 기준 이력 조회 (0) | 2020.03.16 |
---|---|
INDEX 힌트의 세 가지 방식 (0) | 2020.02.23 |
BATCH NL 조인과 TABLE ACCESS BY INDEX ROWID BATCHED 오퍼레이션 (0) | 2020.02.18 |
JPPD에 의한 조인 순서의 이상 동작 (0) | 2020.02.12 |
분산 쿼리와 서브 쿼리 팩토링 (0) | 2020.02.11 |