问题描述
如何在 Oracle 中找到查询使用的执行计划哈希值。我有一个查询的行为非常奇怪,因为有时它在 5 秒内运行,有时需要 2 个多小时。
我已经与 DBA 核对过,他告诉我们有多个执行计划可用于此查询,其中 2 个是坏的,只有 1 个是好的。因此,查询执行所需的时间取决于它选择的计划。
是否有一个查询可用于检查使用了哪个执行计划及其哈希值,以便可以将相同的计划固定在查询上。
解决方法
在运行查询后立即调用 dbms_xplan.display_cursor
将为您提供其计划:
create table t (
c1 int,c2 int
);
insert into t
with rws as (
select level x from dual
connect by level <= 10
)
select x,x from rws;
set serveroutput off
select * from t where c1 = 1;
select *
from table(dbms_xplan.display_cursor(format => 'BASIC LAST'));
PLAN_TABLE_OUTPUT
EXPLAINED SQL STATEMENT:
------------------------
select * from t where c1 = 1
Plan hash value: 1601196873
----------------------------------
| Id | Operation | Name |
----------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS FULL| T |
----------------------------------
create index i on t ( c1 );
select * from t where c1 = 1;
select *
from table(dbms_xplan.display_cursor(format => 'BASIC LAST'));
PLAN_TABLE_OUTPUT
EXPLAINED SQL STATEMENT:
------------------------
select * from t where c1 = 1
Plan hash value: 3241032591
----------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T |
| 2 | INDEX RANGE SCAN | I |
----------------------------------------------------
这仅适用于获取在会话中运行的查询计划。获取其他会话中查询的计划哈希比较棘手。如果它仍在执行,您可以通过查看 from v$session
:
select sid,serial#,sql_id,sql_hash_value
from v$session
where username is not null
运行完成后,您可以通过查看 v$active_session_history
来获取计划;这使用了采样,因此可能不包括您要查找的 SQL。
要控制语句使用哪个计划,请查看 SQL plan management。使用它,您可以create baselines 定义优化器能够用于查询的计划。
,您可以使用 DBA_HIST_SQL_PLAN
视图检查执行计划和相关详细信息。
您将从此视图中看到 plan_hash_value
。
更多详情请见here