执行计划频繁跳变主因是sql plan management基线未生效、未捕获或被绕过;需通过awr查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 能帮你确认 dba_sql_plan_baselines 是否真在起作用,而不是只看 v$sql 里当前缓存的那一个计划。
查 AWR 里有没有基线记录,别只盯 V$SQL
很多人发现 V$SQL 中某 SQL 的 PLAN_HASH_VALUE 变来变去,就急着调统计信息或加 hint。但真正该先查的是:SPM 基线是否已存在、是否 ENABLED=YES 且 ACCEPTED=YES?AWR 不存基线本身,但能通过 DBA_HIST_SQLSTAT 和 DBA_HIST_SQLBIND 回溯该 SQL 在历史快照中是否稳定走基线路径。
- 先确认目标 SQL 的
sql_id:用SELECT sql_id, sql_text FROM dba_hist_sqltext WHERE sql_text LIKE '%your_key%' - 再查它在各快照中是否始终命中同一
plan_hash_value:运行SELECT snap_id, plan_hash_value, executions_delta FROM dba_hist_sqlstat WHERE sql_id = 'xxx' ORDER BY snap_id - 如果
plan_hash_value频繁变化,但DBA_SQL_PLAN_BASELINES显示该 SQL 已有ENABLED=NO或ACCEPTED=NO的基线,说明基线根本没参与决策
用 display_awr 看基线是否实际被使用
dbms_xplan.display_awr 输出的执行计划里,会带一行 Note,明确写是否用了 SPM 基线。这不是靠猜,是 Oracle 实际执行时留下的痕迹。
- 执行
SELECT * FROM TABLE(dbms_xplan.display_awr('abc123xyz', NULL, NULL, 'ADVANCED'))(注意加'ADVANCED'才显示 Note) - 重点找类似这样的行:
Note: SQL plan baseline SQL_PLAN_abc123... used for this statement - 如果没这行,哪怕基线存在,也可能因
optimizer_use_sql_plan_baselines=FALSE、或该 SQL 被设为FIXED=YES后又未演进新计划而失效 - RAC 环境下更要逐实例查:用
gv$sql确认不同inst_id下同一sql_id是否都显示该 Note
为什么 AWR 显示 plan_hash_value 一致,但性能差很多
基线生效 ≠ 性能稳定。PLAN_HASH_VALUE 相同只代表执行树结构一样,不保证节点间真实行为一致。AWR 是唯一能交叉验证这点的工具。
- 查
dba_hist_active_sess_history:对比两个快照中同一sql_id的等待事件分布,比如一个节点大量gc cr block 2-way,另一个没有,说明 RAC 数据块传输不均 - 查
dba_hist_sqlstat中的iowait_delta、cpu_time_delta:即使plan_hash_value相同,I/O 或 CPU 消耗翻倍,大概率是绑定变量窥探导致谓词推入位置不同,或临时表物化时机错位 - 特别注意
DBA_HIST_SQLBIND:如果某次快照中绑定值从'A'变成'Z',而基线只基于前者生成,优化器可能仍走基线,但内部执行路径已劣化
基线“存在”但不生效的三个隐蔽原因
AWR 报告里看不到基线生效痕迹,往往不是配置问题,而是基线本身被“静默绕过”。
-
origin = 'AUTO-CAPTURE'的基线不可信:19c 默认开启optimizer_capture_sql_plan_baselines,但 RAC 下若某节点该参数为 FALSE,该节点生成的计划就不会进基线库,导致跨节点不一致 - SQL 文本有细微差异:空格、注释、大小写不同都会产生新
sql_id,哪怕语义完全一样。用SELECT sql_id, sql_text FROM dba_hist_sqltext对比原始文本,别只信应用日志里的“相同 SQL” - 基线被设为
FIXED=YES后拒绝演进:一旦启用FIXED,哪怕新计划性能好 50%,也不会被考虑。查DBA_SQL_PLAN_BASELINES.FIXED字段,TRUE 就意味着“锁死”,除非手动ALTER_SQL_PLAN_BASELINE
基线不是开关一开就万事大吉的东西;它依赖 SQL 文本一致性、参数同步、绑定值稳定性三者齐备。AWR 不能直接告诉你“为什么没生效”,但它能暴露哪一层断了——是基线缺失、是 Note 缺失、还是 Note 存在但等待事件爆炸。漏掉任一环,你看到的都是“计划没变,但慢得离谱”。











