为什么在这个执行计划(解释计划)中有 HASH JOIN?
Why it has HASH JOIN in this execution plan (explain plan)?
我正在测试一些 Oracle 语句和它们的执行计划,并且正在努力解决这个问题(内部连接 2 table):
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 table WF_TRANSITION
和 WF_VERSION_REQUEST_TYPE
并且不需要 HASH JOIN。
谁能给我解释一下吗?
您有一个适应性计划。数据库将根据处理的行数选择执行 hash join
或 nested loop
。
您可以通过 statistics collector
步骤来判断。这是在 wf_version_reqeuest_types_pk
上计算流出扫描的行数。
如果此数字保持在阈值以下,它将使用 nested loop
。在此之上它会切换到 hash join
.
要找出它做了什么,获取查询的 execution plan。如果您在使用 DBMS_XPlan
时添加 +ADAPTIVE
选项,它会通过在这些操作前加上前缀 -
:
来告诉您哪个连接被丢弃了
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)
我正在测试一些 Oracle 语句和它们的执行计划,并且正在努力解决这个问题(内部连接 2 table):
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 table WF_TRANSITION
和 WF_VERSION_REQUEST_TYPE
并且不需要 HASH JOIN。
谁能给我解释一下吗?
您有一个适应性计划。数据库将根据处理的行数选择执行 hash join
或 nested loop
。
您可以通过 statistics collector
步骤来判断。这是在 wf_version_reqeuest_types_pk
上计算流出扫描的行数。
如果此数字保持在阈值以下,它将使用 nested loop
。在此之上它会切换到 hash join
.
要找出它做了什么,获取查询的 execution plan。如果您在使用 DBMS_XPlan
时添加 +ADAPTIVE
选项,它会通过在这些操作前加上前缀 -
:
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)