我如何找到Oracle中查询使用的执行计划哈希值?

How can i find the execution plan Hash value used by query in Oracle?

如何找到Oracle中查询使用的执行计划哈希值。我有一个查询表现得非常奇怪,有时它会在 5 秒内运行,有时会花费 2 个多小时。

我已经与 DBA 核实过,他告诉我有多个执行计划可用于此查询,其中 2 个是坏的,只有 1 个是好的。因此,查询执行所花费的时间取决于它选择的计划。

是否有查询可用于检查使用了哪个执行计划及其哈希值,以便可以针对查询固定相同的计划。

您可以使用DBA_HIST_SQL_PLAN视图来检查执行计划和相关细节。

您将从该视图中看到 plan_hash_value

可以找到更多详细信息here

在 运行 查询后立即调用 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

一旦完成 运行ning,您也许可以通过查看 v$active_session_history 来获取计划;这使用抽样,因此可能不包括您要查找的 SQL。

要控制语句使用的计划,请查看 SQL plan management. Using this you can create baselines,它定义了优化器能够将哪些计划用于查询。