什么时候使用NO_UNNEST

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很快跑完

posted @ 2014-05-06 12:10  czcb  阅读(425)  评论(0编辑  收藏  举报