21-Oracle 23 ai-Automatic SQL Plan Management(SPM)

小伙伴们,有没有迁移数据库完毕后或是突然某一天在同一个实例上同样的SQL,

性能不一样了、业务反馈卡顿、业务超时等各种匪夷所思的现状。

于是SPM定位开始,OCM考试中SPM必考。

其他的AWR、ASH、SQLHC、SQLT、SQL profile等换作下一个话题,下次填坑。

Oracle SQL Plan Management(SPM)是一种通过控制执行计划稳定性来优化SQL性能的内置机制,其核心原理是通过基线(Baseline)机制管理执行计划的演进,避免因计划突变导致的性能下降。

一、使用场景

当SQL语句的执行计划因统计信息更新、数据库升级、参数调整或索引变更等因素发生变化时,
可能导致性能严重下降(比如没有用索引,使用了全表扫描替代索引扫描)。
关键业务SQL保护:为核心交易SQL绑定已验证的高效执行计划。
灰度验证新计划:通过演化机制(Evolution)测试新计划性能,仅当优于基线时才启用。
迁移与升级保障:在版本升级或硬件变更时维持执行计划一致性。
SPM通过下面步骤定位和解决:

  • 基线(Baseline)机制:记录已知性能良好的执行计划,新生成的计划需验证性能后才被采纳。
  • 演进控制:新计划必须证明优于或等于基线计划,否则仍使用原计划。

二、关键组件

  • Plan History:存储SQL所有曾使用的执行计划(包括未验证的)。
  • Plan Baseline:Plan History的子集,仅包含已验证(ACCEPTED)且稳定的高效计划。
  • SQL Management Base:存储SPM元数据的字典表(位于SYSAUX表空间)。

三、原理解析:工作流程

1. 计划捕获(Plan Capture)​
  • 自动捕获 (需设置参数OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=TRUE):
  • 首次执行的SQL生成计划后,该计划作为初始基线(标记为ENABLED和ACCEPTED)。
  • 后续新计划进入Plan History,但状态为ENABLED, NOT ACCEPTED,需经性能验证才可加入基线。
  • 手动捕获
    • 通过DBMS_SPM包从共享池、SQL调优集(STS)或存储大纲导入计划。
2. 计划选择(Plan Selection)​
  • 优化器决策流程(需启用OPTIMIZER_USE_SQL_PLAN_BASELINES=TRUE):
    2.1 正常解析SQL,生成新执行计划(成本最低)。
    2.2 检查是否存在匹配的SQL Plan Baseline:
    • 若存在ACCEPTED计划 → 直接使用该计划。
  • 若新计划不在Baseline中 → 将其加入Plan History(状态为NOT ACCEPTED)。
    2.3实时回退机制(Oracle 23ai新特性)​ ​:
    • 若新计划性能劣化(如逻辑读激增),自动回退至Baseline中的最优计划。
3. 计划演进(Plan Evolution)​
  • 自动演进
    • 任务SYS_AUTO_SPM_EVOLVE_TASK定期检查未ACCEPTED的计划,通过性能对比(如CPU时间、I/O消耗)决定是否采纳。
    • 参数ACCEPT_PLANS控制是否自动接受更优计划(默认TRUE)。
  • 手动演进
    • 使用 DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE()测试并接受新计划。

四、 Oracle 23 ai 的SPM特性增强:

Real-Time SQL Plan Management (实时SPM)

  • 变化:新增实时检测和修复性能退化的执行计划,无需等待自动任务或手动干预。从捕获、验证到演进全程自动化,减少人工维护成本。
  • 原理:持续监控SQL执行性能,若新计划比基线计划慢,自动回退到基线计划并标记新计划为"UNACCEPTED"。深度集成SQL Monitor,秒级检测执行计划性能退化,自动切换至历史最优计划,无需DBA干预。
  • 优势:减少因计划突变导致的性能风险,尤其适合关键业务SQL。
    与AI Vector Search集成
  • 变化:SPM可管理含AI向量搜索的SQL执行计划(如"VECTOR_DISTANCE()"函数)。
  • 原理:优化器为向量搜索SQL生成计划时,SPM基线会记录并验证其效率。
  • 示例场景:相似性搜索(如"WHERE VECTOR_DISTANCE(embedding, :vec) < 1")的计划稳定性增强。
    Raft复制支持下的分布式SPM
  • 变化:在Globally Distributed Database中,SPM基线支持跨分片同步。
  • 原理:通过Raft共识协议复制基线计划,确保分布式环境下计划一致性。
    增强与In-Memory的协同
  • 变化:SPM优先选择利用In-Memory列存储(如内存连接组)的高效计划。
  • 原理:当"INMEMORY_AUTOMATIC_LEVEL=HIGH"时,SPM自动采纳内存优化计划。

五、配置和实操

​1. 启用实时SPM​
bash 复制代码
-- 启用自动捕获SQL计划基线
SYS@FREE> ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES = TRUE;
System altered
-- 启用实时SPM(默认开启,验证状态)
SYS@FREE> SELECT value FROM v$parameter WHERE name = 'optimizer_use_sql_plan_baselines';
VALUE
------------------------------------------------------------------------------------------------------------------------
TRUE
-- 返回值应为 TRUE
2. 验证实时SPM回退机制​
bash 复制代码
-- 步骤1: 创建测试表
CREATE TABLE spm_test (id NUMBER, data VARCHAR2(100));
INSERT INTO spm_test SELECT rownum, 'Data'||rownum FROM dual CONNECT BY LEVEL <= 10000;
COMMIT;

-- 步骤2: 首次执行(生成初始计划)
SYS@CDB$ROOT> SELECT /*+ REAL_TIME_SPM_TEST */ * FROM spm_test WHERE id = 500;
    ID DATA
______ __________
   500 Data500

-- 步骤3: 可以尝试删除索引
DROP INDEX IF EXISTS spm_test_idx;-- 先创建索引再删除
CREATE INDEX spm_test_idx ON spm_test(id); -- 先创建索引再删除,模拟计划突变

-- 步骤4: 再次执行相同SQL
SELECT /*+ REAL_TIME_SPM_TEST */ * FROM spm_test WHERE id = 500; 
-- 观察执行计划是否回退到全表扫描(原最优计划为索引扫描)

3. 监控SPM状态​

bash 复制代码
--- 查看已捕获的SQL计划基线,查询 SPM 捕获结果
SELECT sql_handle, plan_name, enabled, accepted,optimizer_cost,origin AS capture_source  -- 显示来源为 REAL-TIME
FROM dba_sql_plan_baselines 
WHERE sql_text LIKE '%REAL_TIME_SPM_TEST%';

SQL_HANDLE              PLAN_NAME                         ENABLED    ACCEPTED       OPTIMIZER_COST CAPTURE_SOURCE
_______________________ _________________________________ __________ ___________ _________________ _________________
SQL_64b41bf95ca6b6c6    SQL_PLAN_69d0vz5faddq691cb0adf    YES        NO                          2 AUTO-CAPTURE
SQL_64b41bf95ca6b6c6    SQL_PLAN_69d0vz5faddq696d17023    YES        YES                         1 AUTO-CAPTURE
SQL_64b41bf95ca6b6c6    SQL_PLAN_69d0vz5faddq6f2fc655a    YES        NO                          9 AUTO-CAPTURE
SQL_b1986790bdca8230    SQL_PLAN_b3637k2ywp0jh6ded1a00    YES        YES                         2 AUTO-CAPTURE
SQL_6cf7d7301796c616    SQL_PLAN_6txyr60btdjhq6ded1a00    YES        YES                         2 AUTO-CAPTURE
SQL_9b8aec55051bcab5    SQL_PLAN_9r2rcan2jrkpp6ded1a00    YES        YES                         2 AUTO-CAPTURE
SQL_9cd99fe508c1b86c    SQL_PLAN_9tqczwn4c3f3cb73cade2    YES        YES                         0 AUTO-CAPTURE
--
-- 检查实时回退事件
SELECT sql_id, PLAN_HASH_VALUE
FROM v$sql
WHERE sql_text LIKE '%REAL_TIME_SPM_TEST%';
--
SQL_ID              PLAN_HASH_VALUE
________________ __________________
aq357chxcs0kd             903671040
6xphsvkrns1q1            2664986145
g86t44cwf41r8            2664986145
g03qt7845c4pv             903671040
ajhtavdx2s5t9            2664986145
6kma5qad96t0n            2664986145
6kma5qad96t0n            2664986145
111gdsdj2ft3g            1155944573
6110vngy8zkm4             903671040

9 rows selected.

-- 方案1:SQL Monitor报告(需SQL_ID)
SELECT DBMS_SQL_MONITOR.REPORT_SQL_MONITOR(sql_id => '161f318vx0y63') FROM DUAL;
-- 报告中的Note部分会标注SPM回退事件
SYS@CDB$ROOT> SELECT DBMS_SQL_MONITOR.REPORT_SQL_MONITOR FROM DUAL;
REPORT_SQL_MONITOR
_______________________________________________________________________________________________________________________________
SQL Monitoring Report
SQL Text
------------------------------
begin dbms_swrf_internal.awr_imp(dmpfile=> :mpk_name, dmpdir=>:mbloc, new_dbid=>:dbid, mbtype=>:mbtype, mbcred=>:cred); end;
Global Information
------------------------------
 Status              :  DONE
 Instance ID         :  1
 Session             :  SYS (205:3673)
 SQL ID              :  161f318vx0y63
 SQL Execution ID    :  16777217
 Execution Started   :  06/08/2025 19:58:55
 First Refresh Time  :  06/08/2025 19:59:00
 Last Refresh Time   :  06/08/2025 19:59:01
 Duration            :  6s
 Module/Action       :  MMON_SLAVE/AWR Warehouse Auto-Import
 Service             :  SYS$BACKGROUND
 Program             :  oracle@OL96 (M003)

Global Stats
===============================================================================================================
| Elapsed |   Cpu   |    IO    | Application | Concurrency |  Other   | Buffer | Read | Read  | Write | Write |
| Time(s) | Time(s) | Waits(s) |  Waits(s)   |  Waits(s)   | Waits(s) |  Gets  | Reqs | Bytes | Reqs  | Bytes |
===============================================================================================================
|    6.65 |    5.70 |     0.07 |        0.00 |        0.75 |     0.12 |   108K | 1468 |  19MB |     1 |  8192 |
===============================================================================================================

-- 方案2:检查计划基线状态
SELECT sql_handle, plan_name, enabled, accepted, origin 
FROM DBA_SQL_PLAN_BASELINES 
WHERE sql_text LIKE '%REAL_TIME_SPM_TEST%'
AND origin = 'AUTO-CAPTURE';
-- 若accepted=YES且origin为自动捕获,说明回退成功
----- 检查演进任务报告
SYS@CDB$ROOT> SELECT DBMS_SPM.report_auto_evolve_task FROM dual;

REPORT_AUTO_EVOLVE_TASK
________________________________________________________________________________________________
GENERAL INFORMATION SECTION
---------------------------------------------------------------------------------------------

 Task Information:
 ---------------------------------------------
 Task Name            : SYS_AUTO_SPM_EVOLVE_TASK
 Task Owner           : SYS
 Description          : Automatic SPM Evolve Task
 Execution Name       : EXEC_280
 Execution Type       : SPM EVOLVE
 Scope                : COMPREHENSIVE
 Status               : COMPLETED
 Started              : 06/08/2025 14:00:13
 Finished             : 06/08/2025 14:00:14
 Last Updated         : 06/08/2025 14:00:14
 Global Time Limit    : 3600
 Per-Plan Time Limit  : UNUSED
 Number of Errors     : 0
---------------------------------------------------------------------------------------------

SUMMARY SECTION
---------------------------------------------------------------------------------------------
  Number of plans processed  : 0
  Number of findings         : 0
  Number of recommendations  : 0
  Number of errors           : 0
---------------------------------------------------------------------------------------------
SYS@CDB$ROOT>

六、高级管理脚本​

​1. 手动固定最优计划​
bash 复制代码
--- 查找SQL的SQL_HANDLE
DECLARE
  l_plans PLS_INTEGER;
BEGIN
  l_plans := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(
    sql_id => 'XXXXXXX' -- 替换为实际SQL_ID
  );
END;
/

2. 主动演化计划基线

bash 复制代码
--- 测试并采纳新计划
SYS@CDB$ROOT> SET SERVEROUTPUT ON
SYS@CDB$ROOT> DECLARE
  2    r_report CLOB;
  3  BEGIN
  4    r_report := DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(
  5      sql_handle => 'SQL_9cd99fe508c1b86c' -- 替换为实际SQL_HANDLE
  6    );
  7    DBMS_OUTPUT.PUT_LINE(r_report);
  8  END;
  9* /
GENERAL INFORMATION SECTION
---------------------------------------------------------------------------------------------

 Task Information:
 ---------------------------------------------
 Task Name            : TASK_362
 Task Owner           : SYS
 Execution Name       : EXEC_322
 Execution Type       : SPM EVOLVE
 Scope                : COMPREHENSIVE
 Status               : COMPLETED
 Started              : 06/09/2025 14:58:35
 Finished             : 06/09/2025 14:58:35
 Last Updated         : 06/09/2025 14:58:35
 Global Time Limit    : 2147483646
 Per-Plan Time Limit  : UNUSED
 Number of Errors     : 0
---------------------------------------------------------------------------------------------

SUMMARY SECTION
---------------------------------------------------------------------------------------------
  Number of plans processed  : 0
  Number of findings         : 0
  Number of recommendations  : 0
  Number of errors           : 0
---------------------------------------------------------------------------------------------


PL/SQL procedure successfully completed.

SYS@CDB$ROOT>

七、验证建议

  • 1.使用EXPLAIN PLAN FOR对比回退前后的执行计划差异。
  • 2.结合V$SQL_PLAN和DBA_SQL_PLAN_BASELINES验证计划切换记录。
  • 3.在测试环境模拟高并发场景,观察SPM对稳定性的提升效果。
    效果可能因环境配置而异,建议结合AWR报告和SQL Tuning Advisor进一步优化。
相关推荐
异世界贤狼转生码农1 小时前
MongoDB Windows 系统实战手册:从配置到数据处理入门
数据库·mongodb
QuZhengRong2 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
码农阿豪2 小时前
Windows从零到一安装KingbaseES数据库及使用ksql工具连接全指南
数据库·windows
时序数据说7 小时前
时序数据库市场前景分析
大数据·数据库·物联网·开源·时序数据库
听雪楼主.11 小时前
Oracle Undo Tablespace 使用率暴涨案例分析
数据库·oracle·架构
我科绝伦(Huanhuan Zhou)11 小时前
KINGBASE集群日常维护管理命令总结
数据库·database
妖灵翎幺11 小时前
Java应届生求职八股(2)---Mysql篇
数据库·mysql
HMBBLOVEPDX11 小时前
MySQL的事务日志:
数据库·mysql
YA33312 小时前
java基础(九)sql基础及索引
java·开发语言·sql
weixin_4196583113 小时前
MySQL数据库备份与恢复
数据库·mysql