自适应执行计划是Oracle 12c动态调整执行路径的机制,依赖缓存中的可变框架;当统计信息更新、对象结构变更、优化器参数变动或ACS元数据丢失时,会导致计划缓存失效,丧失自适应能力。

什么是自适应执行计划与计划缓存失效
自适应执行计划(Adaptive Execution Plans)是Oracle 12c引入的优化机制,允许SQL在执行过程中根据运行时统计信息动态调整执行路径(比如从嵌套循环切到哈希连接)。它依赖于计划缓存中已编译的“可变框架”,而非完全重新硬解析。但当底层对象结构、统计信息或优化器环境发生显著变化时,原有自适应计划可能被标记为“失效”,导致下次执行时触发软解析甚至硬解析,从而丢失自适应能力,甚至回归次优计划。
常见导致自适应计划缓存失效的场景
以下变更会直接使已缓存的自适应计划不可复用:
- 统计信息更新:对关联表执行 red">DBMS_STATS.GATHER_TABLE_STATS(尤其指定 NO_INVALIDATE => FALSE 或默认值),会失效所有引用该表的游标,包括其自适应计划分支。
- 对象结构变更:如添加/删除索引、修改列类型、重建分区、执行 ALTER TABLE ... MOVE 等DDL操作,会清空相关SQL的共享池条目。
- 优化器参数变动:修改 optimizer_adaptive_plans、optimizer_features_enable 或 optimizer_mode 等会改变执行计划语义的参数,将导致缓存计划被拒绝使用。
- 绑定变量窥探与ACS失效:若SQL启用了绑定变量窥探(BIND_AWARE),且不同绑定值触发了不同的自适应决策,而ACS(Adaptive Cursor Sharing)元数据因统计刷新或内存压力被清理,也会间接导致自适应逻辑无法延续。
如何识别自适应计划是否实际生效或已失效
不能只看 V$SQL.IS_ADAPTIVE 为YES就认为正在自适应——它仅表示该SQL曾生成过自适应计划。关键要看实时执行行为:
- 查 V$SQL_PLAN 中 OTHER_XML 字段,搜索 adaptive_plan 和 reoptimization 标签,确认是否存在运行时决策节点(如 JOIN_METHOD 动态切换)。
- 对比两次执行的 V$SQL_PLAN.OPERATION 和 OPTIONS:若第一次显示 NESTED LOOPS,第二次变成 HASH JOIN 且 OTHER_XML 有 reopt 记录,说明自适应成功;若两次计划完全一致且无 reopt 信息,可能已被固定或缓存失效后走回退计划。
- 监控 V$SQL_CS_STATISTICS 和 V$SQL_CS_SELECTIVITY,观察ACS是否持续维护多个子游标及其选择率分布——缺失则自适应基础已瓦解。
稳定自适应计划缓存的实用建议
在OLTP或混合负载中平衡性能与稳定性:
- 统计收集时显式设置 NO_INVALIDATE => TRUE(配合 DBMS_STATS.LOCK_TABLE_STATS 可进一步规避),避免批量刷新引发连锁失效。
- 对核心高并发SQL,考虑用 OPTIMIZER_USE_SQL_PLAN_BASELINE=TRUE + 固定自适应计划对应的最终演进版本(通过 DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE 捕获带 reopt 的真实计划),实现“自适应一次、稳定多次”。
- 禁用不必要的自适应特性(如设 optimizer_adaptive_statistics=FALSE)以降低复杂度,除非明确受益于 join method 或 statistics feedback 的场景。
- 定期检查 V$SQL_SHARED_CURSOR 中 REASON 列为 Optimizer mismatch 或 Statistics mismatch 的记录,定位隐性失效源头。










