我正在测试一些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
这是执行计划:
我的问题是为什么我们要进行第6步HASH JOIN,而同时又要进行NESTED LOOP。我认为此NESTED LOOP加入了2个表WF_TRANSITION
和WF_VERSION_REQUEST_TYPE
,并且不需要HASH JOIN。
有人可以向我解释一下吗?
答案 0 :(得分:1)
您有一个自适应计划。数据库将根据处理的行数选择执行hash join
或nested 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)