57-Oracle SQL Profile(23ai)实操

在上一期中说到了SQL Tuning Advisor其中一个影响对象就是SQL Profile,同样在管理和应用开发中,SQL性能优化是个任重道远的工作,低效的SQL语句让应用响应缓慢,用户整体体验下降,拖垮搞蹦整个系统都有可能。Oracle数据库提供了多种组合工具,有的免费有的是需要许可,系统而全面地解决这些性能问题。SQL自动调优(Automatic SQL Tuning)与SQL Profile是从10g就引入的重要特性,提供解决SQL性能问题强大的支持。

一、SQL是否需要自动调优,什么情况下可以接受自动?

数据库的查询优化器(Optimizer)在执行SQL语句前,会根据统计信息、系统参数等因素生成一个或多个执行计划(Execution Plan),并选择一个它认为当前成本已经是最优的计划来执行。

  • 但是在一些因素的影响下,CBO会受影响出次优或是更差的选择,例如:
  1. 统计信息过时或缺失:当表的数据量、数据分布发生显著变化,而统计信息未能及时更新时,优化器基于旧信息做出的判断可能不再准确。
  2. 复杂的查询结构:对于包含多表连接、子查询、复杂谓词的SQL,优化器估算成本的难度会大大增加。(23ai之后有了机器学习是不是有提升)
  • 原生优化器局限性:优化器模型本身可能无法完美处理所有情况。
  • 传统的解决方法通常是在SQL语句中手动添加提示(Hints),以指导优化器选择特定的场景,但这种方式又降存在这些缺陷:
  1. 侵入式修改:需要修改应用程序代码,对于已封装的商业软件或第三方系统,几乎是不可能的任务,且不可延续。
  2. 维护困难:随着数据和业务需求需求调整和运行环境的变化,也许当前有效的Hint,就在不远的下一次失效甚至产生负面影响。
    基于这样的场景和选择,Oracle引入了自动SQL调优机制,提供更智能、非侵入的方式改善SQL执行效率的更优雅的方式。

二、SQL Profile 分类与原理

1. Auto SQL Profile(基于SQL Tuning Advisor)​

本质:优化器辅助统计信息(如基数校正因子 SCALE_ROWS),动态修正执行计划成本计算。
工作原理

  • 分析阶段:校验统计信息、识别异常访问路径(如缺失索引或全表扫描成本失真)。
  • 生成阶段:自动创建校正因子(如将表基数从100修正为100万)。
  • 生效机制:优先使用Profile中的统计信息覆盖默认值,优化器据此重新计算成本。
    优点
  • 自动化高效:一键生成,适合批量优化AWR中的高频低效SQL。
  • 动态适应:随数据变化自动调整,避免计划固化(如新增索引时自动启用)。
  • 低风险:内置成本对比验证,规避极端路径(如不会强制禁用所有索引)。
    缺点
  • 优化局限:无法突破优化器规则(如不能强制嵌套循环替代哈希连接)。
  • 环境依赖:严重依赖当前统计信息,跨环境迁移(测试→生产)可能失效。
  • 黑盒操作:修正逻辑存储在隐藏表 SQLPROF$,问题追溯困难。
2. 手工SQL Profile

本质:Hint组合(从目标执行计划提取Outline Data),强制锁定执行路径。
核心原理

  1. 提取原始SQL的Outline Data。
  2. 通过Hint改写SQL生成目标Outline Data。
  3. 将脚改写的带有Hint的替换原始的版本,生成最终Profile。
    优点
  • 精准控制:绕过优化器决策,强制固定最优路径(如索引扫描、连接顺序)。
  • 优先级碾压:覆盖SQL中的硬编码Hint(如 /*+ FULL(T) */ 无效)。
  • 灵活生效:通过 CATEGORY 按会话/环境隔离(如测试环境用 DEV 类别、生产用PROD)。
    缺点
  • 技术门槛高:需深入理解成本模型,错误设置引发性能恶化(如基数误判导致笛卡尔积)。
  • 维护成本大:表结构变更(如索引删除)需人工重新验证Profile有效性。
  • 过优化风险:强制计划可能失效(如索引失效仍强制扫描,引发全表扫描被禁用)。

三. 实操演示:23 ai上HR.T4SQLPROFILE 表实验​

​步骤1:创建测试环境
bash 复制代码
SYS@CDB$ROOT> alter session set container=FREEPDB1;
-- 建表并模拟插入不均衡数据
CREATE TABLE HR.T4SQLPROFILE AS 
SELECT * FROM DBA_OBJECTS WHERE ROWNUM <= 10000;

INSERT INTO HR.T4SQLPROFILE 
SELECT * FROM DBA_OBJECTS 
WHERE object_id = 100 AND ROWNUM <= 9000;  -- 90% 数据集中

CREATE INDEX HR.IDX_T4SQLPROFILE ON HR.T4SQLPROFILE(object_id);

-- 收集统计信息
BEGIN
  DBMS_STATS.GATHER_TABLE_STATS('HR','T4SQLPROFILE');
END;
/
--PL/SQL procedure successfully completed.
步骤2:自动 Profile 实验

官方文档DBMS_SQLTUNE.ACCEPT_SQL_PROFILE 的 FORCE_MATCH 参数默认值为 FALSE,即必须在 SQL 文本完全匹配时应用 SQL Profile才会被使用,若目标 SQL 文本有改动即使是where 后面的字句查询不一致,原有 SQL Profile 就失效。。所以必须设置*"DBMS_SQLTUNE.ACCEPT_SQL_PROFILE(task_name, force_match=>TRUE);"***

bash 复制代码
-- 低效全表扫描(因 NO_INDEX Hint)
SELECT /*+ NO_INDEX(T) */ * FROM HR.T4SQLPROFILE T WHERE object_id=10;

-- 创建调优任务并接受 Profile
DECLARE
  task_name VARCHAR2(50);
BEGIN
  task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
    sql_text    => 'SELECT /*+ NO_INDEX(T) */ * FROM HR.T4SQLPROFILE T WHERE object_id=10',
    scope       => 'COMPREHENSIVE',
    task_name   => 'AUTO_TUNE_TASK'
  );
  DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name);
  DBMS_SQLTUNE.ACCEPT_SQL_PROFILE(task_name, force_match=>TRUE);
END;
/

-- 验证:计划转为索引扫描
--验证SQL Profile被接受,同时查询走index
SELECT * FROM HR.T4SQLPROFILE WHERE object_id=10; 
--
SYS@CDB$ROOT> SELECT * FROM HR.T4SQLPROFILE WHERE object_id=10;
SYS      C_USER#     10                10 CLUSTER        24-APR-25    
--
SYS@CDB$ROOT> SET AUTOTRACE ON
Autotrace TraceOnly
 Exhibits the performance statistics with silent query output
SELECT * FROM HR.T4SQLPROFILE WHERE object_id=20;
SYS@CDB$ROOT> SELECT * FROM HR.T4SQLPROFILE WHERE object_id=20;

1 row selected.

SQL_ID  cy30yj4480y2q, child number 0
-------------------------------------
SELECT * FROM HR.T4SQLPROFILE WHERE object_id=20

Plan hash value: 2117281514

-------------------------------------------------------------------------
| Id  | Operation                           | Name             | E-Rows |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                  |        |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T4SQLPROFILE     |      1 |
|*  2 |   INDEX RANGE SCAN                  | IDX_T4SQLPROFILE |      1 |
-------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=20)

Note
-----
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level


Statistics
-----------------------------------------------------------
               1  CPU used by this session
               1  CPU used when call started
               5  Requests to/from client
               4  SQL*Net roundtrips to/from client
               4  buffer is not pinned count
             944  bytes received via SQL*Net from client
           67782  bytes sent via SQL*Net to client
               5  calls to get snapshot scn: kcmgss
               2  calls to kcmgcs
               4  consistent gets
               1  consistent gets examination
               1  consistent gets examination (fastpath)
               4  consistent gets from cache
               3  consistent gets pin
               3  consistent gets pin (fastpath)
               1  enqueue releases
               1  enqueue requests
               2  execute count
               1  index range scans
           32768  logical read bytes from cache
               3  no work - consistent read gets
              10  non-idle wait count
               2  opened cursors cumulative
               1  opened cursors current
               1  parse count (hard)
               2  parse count (total)
             169  process last non-idle time
               1  recursive calls
               4  session logical reads
               1  sorts (memory)
            1620  sorts (rows)
               1  table fetch by rowid
               5  user calls
SYS@CDB$ROOT>

四、 SQL Profile 管理指南​

​常用操作

|--------------|------------------------------------------------------------------------------------------------|
| ​操作​ | 命令/视图 |
| ​查看 Profile​ | SELECT name, category, status FROM dba_sql_profiles; |
| ​禁用/启用 | DBMS_SQLTUNE.ALTER_SQL_PROFILE(name=>'PROF1', attribute_name=>'STATUS', value=>'DISABLED'); |
| ​删除 Profile | DBMS_SQLTUNE.DROP_SQL_PROFILE('PROF1'); |
| ​迁移 Profile​ | 使用DBMS_SQLTUNE.PACK_STGTAB_SQLPROF导出导入 |

关键管理场景
  • 环境隔离:通过 CATEGORY 控制 Profile 生效范围(如测试环境用 DEV ,生产用PROD)。
  • 版本升级:使用数据泵导出 SQLPROF$ 表实现跨版本迁移。
  • 性能监控:结合 AWR 报告检查 SQL Profile 的使用效果。
管理SQL Profile
bash 复制代码
-- 查看所有 Profile
SELECT name, category, status, sql_text 
FROM dba_sql_profiles;
--
SYS@CDB$ROOT> SELECT name, category, status, sql_text FROM dba_sql_profiles;
SYS_SQLPROF_0197914a1f230000    DEFAULT     ENABLED    SELECT /*+ NO_INDEX(T) */ * FROM HR.T4SQLPROFILE T WHERE object_id=10


-- 禁用/启用 Profile
BEGIN
  DBMS_SQLTUNE.ALTER_SQL_PROFILE(
    name           => 'SYS_SQLPROF_0197914a1f230000',
    attribute_name => 'STATUS',
    value          => 'DISABLED'  -- 或 'ENABLED'
  );
END;
/

-- 删除 Profile
EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE('SYS_SQLPROF_0197914a1f230000');

五、使用体验​

  1. 自动 Profile 适合解决统计信息不准导致的偶发性性能问题,动态适应数据变化。
  2. 手动 Profile 用于锁定最优计划,尤其适合关键业务 SQL 或第三方系统不可改源码的场景。
  3. 最佳实践
  • 优先尝试自动 Profile
  • 对核心事务 SQL 使用手动 Profile 强控计划
  • 通过 force_match 和 category 提升灵活性和安全性
相关推荐
marteker1 小时前
电通宣布与Criteo战略整合,纳入零售受众数据
大数据·人工智能·零售
摩尔元数1 小时前
质检滞后?物料浪费?MES系统破解传统制造七大死结
大数据·人工智能·制造
ldinvicible1 小时前
基于ARM ubuntu如何进行交叉编译
arm开发·数据库·ubuntu
魔镜魔镜_谁是世界上最漂亮的小仙女2 小时前
SQL-查询
java·数据库·后端
tsxchen2 小时前
在MyBatis中$和#有什么区别
数据库·mybatis
何中应3 小时前
Sharding-jdbc使用(一:水平分表)
java·数据库·后端·mysql
萌新小码农‍3 小时前
Redis后端的简单了解与使用(项目搭建前置)
数据库·redis·缓存
延凡科技3 小时前
低空数联无人机AI智慧巡查平台
大数据·运维·人工智能·无人机·智慧城市·制造
漫步者TZ4 小时前
【StarRocks系列】事务
数据库·starrocks·事务
yczn1234 小时前
3D可视化数字孪生智能服务平台-物联网智控节能控、管、维一体化技术架构
大数据·网络·人工智能