Oracle SQL Plan Management(SPM)技术原理详解

Oracle SQL Plan Management(SPM)技术原理详解

一、概述:为什么需要SPM?

在Oracle数据库中,SQL语句的执行计划(Execution Plan)是优化器(CBO)根据统计信息、系统参数和对象结构生成的逻辑操作步骤。然而,以下场景可能导致执行计划不稳定:

  • 统计信息更新:表或索引的统计信息变化可能导致优化器选择不同的计划。
  • 数据库升级:新版本的优化器算法可能生成更高效(或更低效)的计划。
  • 参数调整:如optimizer_index_cost_adjoptimizer_mode的修改。
  • 索引变更:索引的创建或删除可能改变访问路径。

SPM的核心目标控制执行计划的稳定性,同时允许在验证后引入更优计划。它通过“基线(Baseline)”机制,将已知有效的执行计划纳入受控范围,避免计划突变导致的性能下降。


二、SPM核心原理

1. 执行计划捕获(Plan Capture)

SPM通过两种方式捕获执行计划:

  • 自动捕获(默认关闭):
    OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES参数为TRUE时,所有重复执行的SQL语句首次生成的计划会被自动捕获为“未接受(Unaccepted)”基线。

  • 手动捕获
    从AWR、游标缓存或SQL Tuning Set(STS)中加载历史计划:

    DECLARE
      l_plans PLS_INTEGER;
    BEGIN
      l_plans := DBMS_SPM.LOAD_PLANS_FROM_AWR(begin_time => SYSDATE-7);
    END;
    

关键数据结构
每个基线条目包含:

  • SQL Handle:唯一标识SQL语句的哈希值。
  • Plan Name:执行计划的唯一标识。
  • Origin:计划来源(AUTO-CAPTURE、MANUAL-LOAD等)。
  • Enabled/Accepted:是否启用或已接受该计划。

2. 执行计划选择(Plan Selection)

当SQL语句执行时,优化器会按以下逻辑选择计划:

  1. 生成新计划:基于当前统计信息生成候选计划。
  2. 基线匹配:检查是否存在该SQL的基线计划。
    • 若无基线:直接使用新计划。
    • 若有基线:仅考虑已接受的基线计划。
  3. 成本比较:在基线计划中选择成本最低的(即使新计划成本更低,除非基线允许演化)。

关键参数

  • OPTIMIZER_USE_SQL_PLAN_BASELINES(默认TRUE):启用SPM。
  • SQLPLAN视图:DBA_SQL_PLAN_BASELINES查看基线状态。

3. 执行计划演化(Plan Evolution)

SPM允许将新计划加入基线,但需通过验证:

DECLARE
  l_report CLOB;
BEGIN
  l_report := DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(
    sql_handle => 'SQL_XXXX'
  );
END;

演化过程

  1. 计划比较:对比新计划与基线计划的性能(如解析日志或执行统计)。
  2. 性能验证:若新计划更优,将其标记为“已接受(Accepted)”。
  3. 基线更新:将验证后的计划加入基线。

三、SPM架构与组件

1. 计划历史库(Plan History)

存储所有捕获到的执行计划(包括未接受的),通过DBA_SQL_PLAN_BASELINES查询。

2. 基线库(Baseline Repository)

仅包含已接受的计划,直接影响优化器的选择。

3. 优化器整合

优化器在解析阶段与SPM交互,优先选择基线计划。

4. 管理工具
  • DBMS_SPM包:提供基线加载、演化、固定等API。
  • SQL Tuning Advisor:可建议新计划并自动演化。

四、SPM工作流程

场景示例:新计划引入
  1. 初始状态:基线中存在计划A(成本100)。
  2. 统计信息更新:优化器生成新计划B(成本80)。
  3. 执行阶段
    • 若基线未接受B,仍使用A。
    • 若启用自动演化,B被验证后加入基线。
  4. 切换计划:DBA手动或自动将B设为已接受。

五、SPM高级功能

1. 固定基线(Fixed Baselines)

标记某个计划为“Fixed”,优化器将优先选择它:

BEGIN
  DBMS_SPM.ALTER_SQL_PLAN_BASELINE(
    sql_handle      => 'SQL_XXXX',
    plan_name       => 'PLAN_YYYY',
    attribute_name  => 'FIXED',
    attribute_value => 'YES'
  );
END;
2. 自适应基线(Adaptive Baselines)

结合Oracle 12c的自适应特性,动态调整基线。

3. 基线复制(Baseline Copy)

在开发环境验证后,将基线导出/导入到生产:

-- 导出
DECLARE
  l_plans PLS_INTEGER;
BEGIN
  l_plans := DBMS_SPM.PACK_STGTAB_BASELINE(
    table_name => 'SPM_STAGING_TABLE'
  );
END;

-- 导入
DECLARE
  l_plans PLS_INTEGER;
BEGIN
  l_plans := DBMS_SPM.UNPACK_STGTAB_BASELINE(
    table_name => 'SPM_STAGING_TABLE'
  );
END;

六、SPM与相关技术对比

技术 SPM SQL Profile Outlines
原理 基于基线控制计划选择 通过Hint集合修正优化器估算 强制使用固定Hint组合
灵活性 允许多计划共存并自动演化 单计划修正 单计划强制
维护成本 中(需管理基线) 高(需手动更新)
适用场景 长期计划稳定 紧急修复特定SQL 遗留系统兼容

七、SPM最佳实践

  1. 启用自动捕获(谨慎使用):

    ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=TRUE;
    
  2. 定期演化基线

    BEGIN
      DBMS_SPM.CONFIGURE('AUTO_EVOLVE_TASK', 'ON');
    END;
    
  3. 监控基线状态

    SELECT sql_handle, plan_name, enabled, accepted 
    FROM DBA_SQL_PLAN_BASELINES;
    
  4. 结合AWR分析

    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('sql_id'));
    

八、SPM的局限性

  • 存储开销:基线数据占用SYSAUX表空间。
  • 性能影响:大规模基线可能增加优化器解析时间。
  • 复杂性:需定期维护和监控。

九、总结

Oracle SPM通过基线机制平衡了执行计划的稳定性和灵活性,是应对复杂生产环境的重要工具。合理配置SPM,结合自动演化与手动干预,可显著降低因计划突变导致的性能风险。

你可能感兴趣的:(oracle数据库的牛逼功能,oracle,sql,数据库)