为什么在此执行计划(解释计划)中有HASH JOIN?

时间:2019-08-20 09:47:23

标签: oracle sql-execution-plan

我正在测试一些Oracle语句及其执行计划,并为此而烦恼(内部联接2表):

SELECT COUNT(*) 
FROM WF_TRANSITION T, 
     WF_VERSION_REQUEST_TYPE VRT 
WHERE T.FK_VS_REQUEST_TYPE_ID = VRT.VS_REQUEST_TYPE_ID + 0

这是执行计划:

Execution plan for above SQL statement

我的问题是为什么我们要进行第6步HASH JOIN,而同时又要进行NESTED LOOP。我认为此NESTED LOOP加入了2个表WF_TRANSITIONWF_VERSION_REQUEST_TYPE,并且不需要HASH JOIN。 有人可以向我解释一下吗?

1 个答案:

答案 0 :(得分:1)

您有一个自适应计划。数据库将根据处理的行数选择执行hash joinnested loop

您可以通过statistics collector步骤来告知。这是对wf_version_reqeuest_types_pk上扫描流出的行进行计数。

如果该数字保持在阈值以下,它将使用nested loop。在此上方,它将切换到hash join

要弄清楚它是做什么的,请获取查询的execution plan。如果在使用+ADAPTIVE时添加了DBMS_XPlan选项,则会通过在这些操作前面加上-来向您显示哪个连接被丢弃:

set serveroutput off

select /*+ gather_plan_statistics */*
from   hr.employees e
join   hr.departments d
on     e.department_id = d.department_id;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'ROWSTATS LAST +ADAPTIVE'));

Plan hash value: 4179021502                                                                 

----------------------------------------------------------------------------------------    
|   Id  | Operation                     | Name              | Starts | E-Rows | A-Rows |    
----------------------------------------------------------------------------------------    
|     0 | SELECT STATEMENT              |                   |      1 |        |    106 |    
|  *  1 |  HASH JOIN                    |                   |      1 |    106 |    106 |    
|-    2 |   NESTED LOOPS                |                   |      1 |    106 |     27 |    
|-    3 |    NESTED LOOPS               |                   |      1 |        |     27 |    
|-    4 |     STATISTICS COLLECTOR      |                   |      1 |        |     27 |    
|     5 |      TABLE ACCESS FULL        | DEPARTMENTS       |      1 |     27 |     27 |    
|- *  6 |     INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |      0 |        |      0 |    
|-    7 |    TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |      0 |      4 |      0 |    
|     8 |   TABLE ACCESS FULL           | EMPLOYEES         |      1 |    107 |    107 |    
----------------------------------------------------------------------------------------    

Predicate Information (identified by operation id):                                         
---------------------------------------------------                                         

   1 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")                                      
   6 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")                                      

Note                                                                                        
-----                                                                                       
   - this is an adaptive plan (rows marked '-' are inactive)