{section}
{column:width=50}
Subquery Unnesting 에 의한 Hash Semi Join
SQL> -- Subquery Unnesting 에 의한 Hash Semi Join --
SQL> SELECT COUNT(*)
2 FROM (SELECT /*+ gather_plan_statistics */
3 t1.c1, t1.c2
4 FROM t1
5 WHERE t1.c1 IN (SELECT t2.c1 FROM t2)
6 )
7 ;
1000
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID 9g821jv5f7kgv, child number 0
-------------------------------------
SELECT COUNT(*) FROM (SELECT /*+ gather_plan_statistics */ t1.c1, t1.c2 FROM t1 WHERE
t1.c1 IN (SELECT t2.c1 FROM t2) )
Plan hash value: 911817144
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------
| 1 | SORT AGGREGATE | | 1 | 1 | | 1 |00:00:00.01 | 31 | | | |
|* 2 | HASH JOIN RIGHT SEMI | | 1 | 999 | 10 (10)| 1000 |00:00:00.01 | 31 | 1066K| 1066K| 1178K (0)|
| 3 | INDEX FAST FULL SCAN| T2_N1 | 1 | 1000 | 2 (0)| 1000 |00:00:00.01 | 7 | | | |
| 4 | INDEX FAST FULL SCAN| T1_N1 | 1 | 10000 | 7 (0)| 10000 |00:00:00.01 | 24 | | | |
----------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T1"."C1"="T2"."C1")
21 개의 행이 선택되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
No_Unnest 로 인한 Filter Operation
SQL> -- No_Unnest 로 인한 Filter Operation --
SQL> SELECT COUNT(*)
2 FROM (SELECT /*+ gather_plan_statistics */
3 t1.c1, t1.c2
4 FROM t1
5 WHERE t1.c1 IN (SELECT /*+ No_Unnest */ t2.c1 FROM t2)
6 )
7 ;
1000
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID 7hx47wqmyqn07, child number 0
-------------------------------------
SELECT COUNT(*) FROM (SELECT /*+ gather_plan_statistics */ t1.c1, t1.c2
FROM t1 WHERE t1.c1 IN (SELECT /*+ No_Unnest */ t2.c1 FROM t2) )
Plan hash value: 645528743
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------
| 1 | SORT AGGREGATE | | 1 | 1 | | 1 |00:00:00.05 | 20038 |
|* 2 | FILTER | | 1 | | | 1000 |00:00:00.01 | 20038 |
| 3 | TABLE ACCESS FULL| T1 | 1 | 10000 | 11 (0)| 10000 |00:00:00.01 | 38 |
|* 4 | INDEX RANGE SCAN | T2_N1 | 10000 | 1 | 1 (0)| 1000 |00:00:00.03 | 20000 |
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter( IS NOT NULL)
4 - access("T2"."C1"=:B1)
22 개의 행이 선택되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
Top-N Query 로 인한 Nested Loops Semi Join
SQL> -- Top-N Query 로 인한 Nested Loops Semi Join --
SQL> SELECT *
2 FROM (SELECT /*+ gather_plan_statistics */
3 t1.c1, t1.c2
4 FROM t1
5 WHERE t1.c1 IN (SELECT t2.c1 FROM t2)
6 )
7 WHERE ROWNUM <= 1
8 ;
636 dummy
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID dqgpjf25wnphs, child number 0
-------------------------------------
SELECT * FROM (SELECT /*+ gather_plan_statistics */ t1.c1, t1.c2 FROM t1 WHERE t1.c1
IN (SELECT t2.c1 FROM t2) ) WHERE ROWNUM <= 1
Plan hash value: 3833757213
----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------
|* 1 | COUNT STOPKEY | | 1 | | | 1 |00:00:00.01 | 11 | | | |
|* 2 | HASH JOIN RIGHT SEMI | | 1 | 999 | 5 (20)| 1 |00:00:00.01 | 11 | 1066K| 1066K| 1135K (0)|
| 3 | INDEX FAST FULL SCAN| T2_N1 | 1 | 1000 | 2 (0)| 1000 |00:00:00.01 | 7 | | | |
| 4 | TABLE ACCESS FULL | T1 | 1 | 10000 | 2 (0)| 1 |00:00:00.01 | 4 | | | |
----------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=1)
2 - access("T1"."C1"="T2"."C1")
22 개의 행이 선택되었습니다.
SQL> SELECT *
2 FROM (SELECT /*+ gather_plan_statistics */
3 t1.c1, t1.c2
4 FROM t1
5 WHERE t1.c1 IN (SELECT t3.c1 FROM t3)
6 )
7 WHERE ROWNUM <= 1
8 ;
1 dummy
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID 912xytkf43uu6, child number 0
-------------------------------------
SELECT * FROM (SELECT /*+ gather_plan_statistics */
t1.c1, t1.c2 FROM t1 WHERE t1.c1 IN (SELECT t3.c1
FROM t3) ) WHERE ROWNUM <= 1
Plan hash value: 1263059105
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers | Reads |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 (100)| 1 |00:00:00.03 | 10 | 1 |
|* 1 | COUNT STOPKEY | | 1 | | | 1 |00:00:00.03 | 10 | 1 |
| 2 | NESTED LOOPS SEMI | | 1 | 2 | 2 (0)| 1 |00:00:00.03 | 10 | 1 |
| 3 | TABLE ACCESS FULL| T1 | 1 | 10000 | 2 (0)| 946 |00:00:00.01 | 7 | 0 |
|* 4 | INDEX RANGE SCAN | T3_N1 | 946 | 1 | 0 (0)| 1 |00:00:00.03 | 3 | 1 |
-------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=1)
4 - access("T1"."C1"="T3"."C1")
24 개의 행이 선택되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
Top-N Query 가 Filter Operation 으로 풀린다면?
SQL> -- No_Unnest 로 인한 Filter Operation Top-N Query --
SQL> SELECT *
2 FROM (SELECT /*+ gather_plan_statistics */
3 t1.c1, t1.c2
4 FROM t1
5 WHERE t1.c1 IN (SELECT /*+ No_Unnest */ t2.c1 FROM t2)
6 )
7 WHERE ROWNUM <= 1
8 ;
636 dummy
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID czy3b9qqwk0uh, child number 0
-------------------------------------
SELECT * FROM (SELECT /*+ gather_plan_statistics */ t1.c1, t1.c2
FROM t1 WHERE t1.c1 IN (SELECT /*+ No_Unnest */ t2.c1 FROM t2) ) WHERE
ROWNUM <= 1
Plan hash value: 2386917197
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------
|* 1 | COUNT STOPKEY | | 1 | | | 1 |00:00:00.01 | 6 |
|* 2 | FILTER | | 1 | | | 1 |00:00:00.01 | 6 |
| 3 | TABLE ACCESS FULL| T1 | 1 | 10000 | 11 (0)| 1 |00:00:00.01 | 4 |
|* 4 | INDEX RANGE SCAN | T2_N1 | 1 | 1 | 1 (0)| 1 |00:00:00.01 | 2 |
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=1)
2 - filter( IS NOT NULL)
4 - access("T2"."C1"=:B1)
24 개의 행이 선택되었습니다.
{column}
{column:width=50}
{column}
{section}
{section}
{column:width=50}
인덱스 조건으로 인한 Nested Loops Semi Join
SQL> -- 인덱스 조건으로 인한 Nested Loops Semi Join --
SQL> SELECT /*+ gather_plan_statistics */
2 t1.c1, t1.c2
3 FROM t1
4 WHERE t1.c1 IN (SELECT t2.c1 FROM t2)
5 AND t1.c1 = 1
6 ;
1 dummy
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor(null,null,'allstats cost last'));
SQL_ID 7za75sb3zfp6r, child number 0
-------------------------------------
SELECT /*+ gather_plan_statistics */ t1.c1, t1.c2 FROM t1 WHERE t1.c1 IN (SELECT t2.c1
FROM t2) AND t1.c1 = 1
Plan hash value: 2914088042
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------------
| 1 | NESTED LOOPS SEMI | | 1 | 1 | 3 (0)| 1 |00:00:00.01 | 6 |
| 2 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 1 | 2 (0)| 1 |00:00:00.01 | 4 |
|* 3 | INDEX RANGE SCAN | T1_N1 | 1 | 1 | 1 (0)| 1 |00:00:00.01 | 3 |
|* 4 | INDEX RANGE SCAN | T2_N1 | 1 | 1 | 1 (0)| 1 |00:00:00.01 | 2 |
-------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("T1"."C1"=1)
4 - access("T2"."C1"=1)
filter("T1"."C1"="T2"."C1")
23 개의 행이 선택되었습니다.
SQL>
{column}
{column:width=50}
{column}
{section}