一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

为何Oracle ASH报告中的SQL执行计划散列值(Plan Hash)会变

时间:2026-06-19 08:43:46 编辑:袖梨 来源:一聚教程网

PLAN_HASH_VALUE变化说明执行路径真变了,不是采样误差;ASH中同一SQL_ID的sql_plan_hash_value不一致,表明优化器实际选择了不同物理路径,如索引扫描变全表扫描,常见于绑定变量值差异、统计信息过期或RAC节点差异。

PLAN_HASH_VALUE 变化说明执行路径真变了,不是采样误差

ash 里看到同一 sql_idsql_plan_hash_value 在不同采样点不一致,基本可断定执行计划发生了切换——比如前一秒走 index range scan,后一秒变成 full table scan。这不是 ash 记录不准,而是优化器在运行时真实选择了不同物理路径。ash 每秒采样一次活跃会话,天然比 awr(每小时快照)更敏感,能抓到计划切换的临界瞬间。

常见触发原因:绑定变量值、统计信息、RAC 节点差异

PLAN_HASH_VALUE 变化背后是优化器重估算的结果,和语句文本无关。容易被忽略的几个点:

  • 绑定变量值差异大(如 :status = 'A' 返回 10 行 vs :status = 'Z' 返回 500 万行),而优化器按平均基数估算,导致不同取值触发不同计划
  • 统计信息过期或只更新了部分分区(DBA_TAB_STATISTICSLAST_ANALYZED 时间不一致),尤其在分区表上容易引发计划漂移
  • RAC 环境下各节点缓存的统计信息或绑定值不一致,同一 SQL_ID 在 node1 走索引、node2 走全表,gv$active_session_history 里就会混着多个 sql_plan_hash_value
  • SQL_PROFILESQL Plan Baseline 虽然没变,但它们只提供辅助统计或候选计划,不锁定唯一执行路径;优化器仍可能根据当前环境选另一个合法计划

别只看 hash 值,要查谓词下推和基数预估是否合理

两个 PLAN_HASH_VALUE 不同,不一定代表性能变差;但相同 PLAN_HASH_VALUE 也可能性能天差地别——关键看实际执行时的谓词位置和行数预估是否失真。

  • DBMS_XPLAN.DISPLAY_CURSOR('xxx', null, 'BASIC +PEEKED_BINDS') 查当前执行计划,重点核对 access_predicates 是否落在索引字段上、filter_predicates 是否被推到存储层
  • 对比 cardinality 预估值和实际返回行数(从 v$sql_plan_statistics_alloutput_rows 字段获取),若差 10 倍以上,说明优化器“看走眼”,即使 plan hash 不变,physical reads 也可能暴涨
  • PLAN_HASH_VALUE 不校验临时表物化时机、buffer cache 命中率、甚至并行度调整,这些都会影响真实 I/O 和耗时

怎么确认是不是真漂移?用 AWR 历史比对最可靠

单看 ASH 里的 sql_plan_hash_value 容易误判,因为样本可能来自解析、阻塞或 PL/SQL 循环调用。真正确认计划是否漂移,得回溯 AWR:

  • 运行 SELECT plan_hash_value, COUNT(*), MIN(sample_time), MAX(sample_time) FROM dba_hist_sql_plan p JOIN dba_hist_sqlstat s USING (sql_id, plan_hash_value) WHERE sql_id = 'your_sql_id' AND sample_time > SYSDATE - 7 GROUP BY plan_hash_value —— 如果返回多行,就是确凿证据
  • 再用 DBMS_XPLAN.DISPLAY_AWR('your_sql_id', 123456789) 分别拉出不同 plan_hash_value 对应的完整计划,逐行比对 OPERATIONOPTIONSOBJECT_NAME 是否一致
  • 注意:如果 dba_hist_sql_plan 查不到历史记录,可能是隐含参数 _cursor_plan_cache_threshold 截断了高频 SQL 的计划保存量,不是没发生,是没存住

真正难处理的不是 plan hash 变了,而是它没变但性能崩了——这时候得盯紧谓词有效性、临时段溢出、以及 buffer cache 中那些“看起来命中了,其实要反复 re-read”的脏块。

热门栏目