awr是唯一能验证sql plan baseline是否真实生效的工具;需查dba_hist_sqlstat中plan_hash_value是否稳定,多值表明计划漂移,再用dbms_xplan.display_awr('advanced')确认note中是否有“sql plan baseline used”,并核对dba_sql_plan_baselines中enabled/accepted/fixed三态及rac多实例一致性。
awr 是唯一能验证 sql plan baseline 是否真实生效的工具——v$sql 只反映当前缓存的计划,而 awr 记录的是历史中真正被执行过的路径。基线存在 ≠ 基线被用,必须查 awr 才能确认优化器是否真的按基线走。
查 AWR 里 plan_hash_value 是否稳定
执行计划跳变的第一手证据,就藏在 DBA_HIST_SQLSTAT 中。如果过去 7 天内同一个 sql_id 出现多个 plan_hash_value,说明计划确实漂移了,基线大概率没起作用。
- 运行这个查询(替换
'your_sql_id'):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 ORDER BY MIN(sample_time);
- 返回多行 → 计划已漂移,需继续查基线状态;只有一行 → 问题不在执行路径上(比如 I/O 抖动、锁争用)
-
DBA_HIST_SQL_PLAN默认每sql_id最多存 1000 行计划(受_cursor_plan_cache_threshold控制),高频 SQL 可能被截断,空结果不等于没历史计划
用 DISPLAY_AWR 看 Note 里有没有“SQL plan baseline used”
DBMS_XPLAN.DISPLAY_AWR 的输出里,只有加 'ADVANCED' 格式参数,才会在 Note 区显示基线是否被实际调用。这是 Oracle 执行时留下的硬证据,不是推测。
- 必须带
'ADVANCED':SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('abc123xyz', NULL, NULL, 'ADVANCED')); - 重点找这行:
Note: SQL plan baseline SQL_PLAN_abc123 used for this statement - 没这行?哪怕
DBA_SQL_PLAN_BASELINES显示ENABLED=YES,也可能因optimizer_use_sql_plan_baselines=FALSE、或该基线被设为FIXED=YES后未演进新计划而失效 - RAC 环境下,得用
GV$SQL或DBA_HIST_ACTIVE_SESS_HISTORY确认不同inst_id是否都出现该 Note,单节点查不准
核对 DBA_SQL_PLAN_BASELINES 中的三态字段
基线能否参与决策,取决于三个布尔字段的组合:不是只要 ENABLED=YES 就够了,ACCEPTED 和 FIXED 同样关键。
-
ENABLED=YES:基线可被优化器考虑;=NO→ 直接忽略,不管其他字段 -
ACCEPTED=YES:该计划已被验证为可用;=NO且ENABLED=YES→ 仅用于演进对比,不会被选中 -
FIXED=YES:强制只用这个计划,但会阻断自动演进;若长期不更新,可能变成性能瓶颈 - RAC 下要确认所有实例的
DBA_SQL_PLAN_BASELINES内容一致,尤其origin字段:值为MANUAL-LOAD才可控;AUTO-CAPTURE需确保所有节点optimizer_capture_sql_plan_baselines=TRUE
为什么 AWR 显示 plan_hash_value 一致,但性能差很多
PLAN_HASH_VALUE 相同只代表执行树结构一样,不保证每个节点的实际行为一致。AWR 是唯一能交叉验证这点的工具。
- 查
DBA_HIST_ACTIVE_SESS_HISTORY对比两个快照中同一sql_id的等待事件分布,比如一个节点大量gc cr b,另一个全是db file sequential read - 看
elapsed_time_total / executions_total是否同步飙升 —— 若计划没变但耗时翻倍,问题大概率在 I/O 延迟、内存压力或 RAC 节点间数据块争用 - 注意
DBA_HIST_SQLSTAT中的buffer_gets_delta和disk_reads_delta,相同计划下这两个值突增,往往意味着统计信息失真或绑定变量窥探失效
最常被忽略的一点:AWR 快照本身可能配置过松——默认 60 分钟一次、保留 8 天,在性能抖动持续时间短于快照间隔时,根本抓不到异常瞬间。查 DBA_HIST_WR_CONTROL 确认真实配置,别信文档默认值。











