select * from test a where object_id in (select department_id
from hr.dept_1 dept
where department_id IN (select department_id from hr.employees_1 emp));
SQL> select count(*) from test;
COUNT(*)
----------
2319328
SQL> select count(*) from dept_1;
COUNT(*)
----------
4194304
SQL> select count(*) from employees_1;
COUNT(*)
----------
3506176
SQL> (select department_id
from hr.dept_1 dept
where department_id IN (select department_id from hr.employees_1 emp)) 2 3
4 ;
DEPARTMENT_ID
-------------
10
20
SQL> set linesize 200
SQL> set pagesize 200
SQL> explain plan for select * from test a where object_id in (select department_id
from hr.dept_1 dept
where department_id IN (select department_id from hr.employees_1 emp)); 2 3
Explained.
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------
Plan hash value: 717021958
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 9747 (7)| 00:01:57 |
| 1 | VIEW | VM_NWVW_2 | 1 | 207 | 9747 (7)| 00:01:57 |
| 2 | HASH UNIQUE | | 1 | 226 | 9747 (7)| 00:01:57 |
|* 3 | HASH JOIN | | 14M| 3134M| 9264 (2)| 00:01:52 |
|* 4 | HASH JOIN | | 46 | 10212 | 7400 (1)| 00:01:29 |
| 5 | TABLE ACCESS FULL | DEPT_1 | 2 | 6 | 3 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | TEST | 2511K| 524M| 7389 (1)| 00:01:29 |
| 7 | INDEX FAST FULL SCAN| EMPLOYEES_1_IDX1 | 3508K| 13M| 1819 (1)| 00:00:22 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("DEPARTMENT_ID"="DEPARTMENT_ID")
4 - access("OBJECT_ID"="DEPARTMENT_ID")
Note
-----
- dynamic sampling used for this statement (level=2)
24 rows selected.
此时子查询被展开,直接dept_1和test进行了HASH JOIN 两表记录数分别为4194304和2319328 SQL根本跑不出结果
利用NO_UNNEST,阻止子查询展开:
SQL> select * from test a where object_id in (select department_id
from hr.dept_1 dept
where department_id IN (select /*+ NO_UNNEST */ department_id from hr.employees_1 emp));
2 3
64 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1506439343
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 23 | 5060 | 7403 (1)| 00:01:29 |
|* 1 | HASH JOIN RIGHT SEMI| | 23 | 5060 | 7403 (1)| 00:01:29 |
| 2 | VIEW | VW_NSO_1 | 1 | 13 | 6 (0)| 00:00:01 |
|* 3 | FILTER | | | | | |
| 4 | TABLE ACCESS FULL| DEPT_1 | 2 | 6 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | EMPLOYEES_1_IDX1 | 2 | 8 | 3 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | TEST | 2511K| 495M| 7389 (1)| 00:01:29 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("OBJECT_ID"="DEPARTMENT_ID")
3 - filter( EXISTS (SELECT /*+ NO_UNNEST */ 0 FROM "HR"."EMPLOYEES_1" "EMP"
WHERE "DEPARTMENT_ID"=:B1))
5 - access("DEPARTMENT_ID"=:B1)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
80269 consistent gets
48802 physical reads
0 redo size
4119 bytes sent via SQL*Net to client
463 bytes received via SQL*Net from client
6 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
64 rows processed
此时SQL很快跑完