Oracle SQL Tuning Advisor调优工具

Oracle SQL Tuning Advisor调优工具

一、概述

在Oracle 10g及更高版本中,SQL Tuning Advisor是优化SQL性能的核心工具之一。它的任务是分析指定的SQL语句,并提出一系列改进建议,包括:

  1. 统计信息建议:发现缺失或过时的对象统计信息。
  2. SQL Profile 建议:发现优化器估算错误,建议创建 Profile 来修正估算。
  3. 索引建议:建议创建新索引以提升性能。
  4. SQL 重构建议:建议改写 SQL 语句(如去重、改写子查询)。

二、为什么SQL Tuning Advisor能找到更好的执行计划?

2.1 工作原理

SQL Tuning Advisor将给定的SQL语句委派给自动调优优化器(Automatic Tuning Optimizer) 进行处理。该组件是Oracle查询优化器的一部分,但拥有与普通优化器不同的工作模式:

特性 普通优化器(Normal Optimizer) 自动调优优化器(Automatic Tuning Optimizer)
目标 在毫秒级内生成执行计划 花较长时间(秒到分钟级)寻找更优计划
技术 常规成本估算、统计信息 假设分析(What-if) 、强化动态采样
验证 无 可实际执行计划中的部分步骤,比较估算值与实际值
用途 日常SQL解析 SQL调优顾问的专用引擎

关键结论:两者职责不同------优化器必须快速响应,而调优顾问可以投入更多时间进行深度探索,因此有时能找到优化器在第一时刻未能发现的更优执行计划。

2.2 输入方式

SQL Tuning Advisor的核心接口是DBMS_SQLTUNE程序包,它可以接受以下四种形式的SQL输入:

  1. SQL文本:直接提供完整的SQL语句。
  2. 共享池中的SQL :通过指定SQL_ID引用已在共享池中解析的SQL。
  3. AWR中的SQL :通过指定SQL_ID引用存储在AWR资料库中的历史SQL。
  4. SQL调优集(SQL Tuning Set) :一组SQL语句的集合,适用于批量调优。

三、创建自定义存储过程(封装)

在实际工作中,最常用的是通过SQL_ID进行调优。为了简化操作流程,我们可以创建一个存储过程。该过程接收 SQL_ID,自动创建调优任务、执行任务,并输出查看报告的命令。

脚本说明:

  • 输入 :p_sql_id (目标 SQL 的 ID)。
  • 输出:调优任务名称及查询报告的命令。
sql 复制代码
-- 以 SYS 用户运行
CREATE OR REPLACE PROCEDURE p_create_sqltuning_task(p_sql_id VARCHAR2) IS
    v_tuning_task VARCHAR2(30);
    v_sql_id      v$session.sql_id%TYPE;
BEGIN
    v_sql_id := p_sql_id;

    -- 1. 创建调优任务
    v_tuning_task := DBMS_SQLTUNE.CREATE_TUNING_TASK(sql_id => v_sql_id);

    -- 2. 执行调优任务
    DBMS_SQLTUNE.EXECUTE_TUNING_TASK(v_tuning_task);

    -- 3. 输出任务名称和查看报告的SQL命令
    DBMS_OUTPUT.PUT_LINE('This Tuning task name is : ' || v_tuning_task);
    DBMS_OUTPUT.PUT_LINE('-------------Please using follow command query SQL tuning report!------------');
    DBMS_OUTPUT.PUT_LINE('set linesize 200 pagesize 9999');
    DBMS_OUTPUT.PUT_LINE('set long 100000');
    DBMS_OUTPUT.PUT_LINE('select dbms_sqltune.report_tuning_task(''' || v_tuning_task || ''') from dual;');
END;
/

四、案例

1、准备工作

复制代码
-- 准备表和数据
SQL> create table tab_1 as select * from dba_objects;
Table created.
SQL> insert into tab_1 select * from tab_1;
72357 rows created.
SQL> commit;
Commit complete.

-- 收集统计信息
BEGIN

  DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'dbmon',
                                TABNAME=>'tab_1',
                                ESTIMATE_PERCENT=>1,
                                METHOD_OPT=>'FOR ALL COLUMNS SIZE 1',
                                NO_INVALIDATE=>FALSE,
                                CASCADE=>TRUE,
                                DEGREE => 1); 
END; 
/



set linesize 200 pagesize 999
col owner format a20
col object_Name format a20
col sql_text format a40

-- 发起待调优的SQL语句
SELECT /* sql_tuning_test */ object_id,object_name,owner FROM tab_1 WHERE object_id=50;

 OBJECT_ID OBJECT_NAME          OWNER
---------- -------------------- --------------------
        50 I_COL3               SYS
        50 I_COL3               SYS

-- 查询SQL语句的SQL_ID
SELECT sql_text, sql_id, hash_value, child_number 
  FROM v$sql 
 WHERE sql_text LIKE '%sql_tuning_test%' 
AND sql_text NOT LIKE '%v$sql%';

SQL_TEXT                                 SQL_ID        HASH_VALUE CHILD_NUMBER
---------------------------------------- ------------- ---------- ------------
SELECT /* sql_tuning_test */ object_id,o 58x341t6ddxzk 1289156594            0
bject_name,owner FROM tab_1 WHERE object
_id=50

2、执行调优任务

假设我们有一个SQL_ID为58x341t6ddxzk的SQL语句,调用存储过程来启动调优任务:

sql 复制代码
-- 执行调优任务
set serveroutput on
EXEC p_create_sqltuning_task('58x341t6ddxzk');

-- 输出内容
-------------Please using follow command query SQL tuning report!------------
set linesize 200 pagesize 9999
set long 100000
select dbms_sqltune.report_tuning_task('TASK_13') from dual;

3、查看生成的调优报告

按照存储过程输出的提示,执行以下命令查看详细的调优报告:

sql 复制代码
set linesize 200 pagesize 9999
set long 100000
select dbms_sqltune.report_tuning_task('TASK_13') from dual;

4、调优报告分析

下面我们逐段分析这份报告的内容。

第一部分:基本信息
复制代码
DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_13')
--------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : TASK_13
Tuning Task Owner  : SYS
Workload Type      : Single SQL Statement
Scope              : COMPREHENSIVE
Time Limit(seconds): 1800
Completion Status  : COMPLETED
Started at         : 08/14/2026 16:43:58
Completed at       : 08/14/2026 16:43:58

-------------------------------------------------------------------------------
Schema Name   : DBMON
Container Name: PDB1
SQL ID        : 58x341t6ddxzk
SQL Text      : SELECT /* sql_tuning_test */ object_id,object_name,owner FROM
                tab_1 WHERE object_id=50

信息解读:

  • 调优任务在1秒内完成(16:43:58 - 6:43:58),远低于1800秒的时间限制。
  • 目标SQL的具体语句。
第二部分:发现的问题与建议(共1个)

发现1:建议创建索引

复制代码
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------

1- Index Finding (see explain plans section below)
--------------------------------------------------
  The execution plan of this statement can be improved by creating one or more
  indices.

  Recommendation (estimated benefit: 99.62%)
  ------------------------------------------
  - Consider running the Access Advisor to improve the physical schema design
    or creating the recommended index.
    create index DBMON.IDX$$_000D0001 on DBMON.TAB_1("OBJECT_ID","OBJECT_NAME",
    "OWNER");

  Rationale
  ---------
    Creating the recommended indices significantly improves the execution plan
    of this statement. However, it might be preferable to run "Access Advisor"
    using a representative SQL workload as opposed to a single statement. This
    will allow to get comprehensive index recommendations which takes into
    account index maintenance overhead and additional space consumption.

解读:

  • 调优顾问发现创建索引 可以将响应时间提升99.62%。
  • 建议创建复合索引(三列组合 ------ OBJECT_ID、OBJECT_NAME、OWNER)

报告特别指出:

虽然为单条 SQL 创建索引能显著改善执行计划,但更推荐的做法是使用 Access Advisor ,基于一个有代表性的 SQL 工作负载来获取综合性的索引建议。

这是因为:

  • 单条 SQL 的索引建议可能与其他 SQL 的需求冲突。
  • Access Advisor 会综合考虑索引维护开销(DML 时的额外写入)和存储空间消耗,给出全局最优方案。
第三部分:执行计划对比

原始执行计划

复制代码
1- Original
-----------
Plan hash value: 2157271952

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     2 |    90 |   795   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TAB_1 |     2 |    90 |   795   (1)| 00:00:01 |
---------------------------------------------------------------------------

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

   1 - filter("OBJECT_ID"=50)

问题诊断:

  • 执行了全表扫描 (TABLE ACCESS FULL),代价795。

创建索引后的执行计划

复制代码
2- Using New Indices
--------------------
Plan hash value: 1688321801

-----------------------------------------------------------------------------------
| Id  | Operation        | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                |     2 |    90 |     3   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX$$_000D0001 |     2 |    90 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

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

   1 - access("OBJECT_ID"=50)

-------------------------------------------------------------------------------

对比分析:

  • 执行索引范围扫描,代价3。

5、清理调优任务

sql 复制代码
-- 调优完成后,及时删除任务
EXEC DBMS_SQLTUNE.DROP_TUNING_TASK('TASK_13');
相关推荐
Omics Pro1 小时前
空间组学!医学代谢显微工具
数据库·人工智能·算法·机器学习·自然语言处理
Yyyyyy~1 小时前
[mysql]day1
数据库·mysql
Elastic 中国社区官方博客2 小时前
两个依赖和一个配置块:通过 Prometheus 远程写入将 Spring Boot 指标发送到 Elasticsearch
大数据·数据库·spring boot·elasticsearch·搜索引擎·全文检索·prometheus
JosieBook2 小时前
【数据库】MySQL 实战精通系列 · 第2篇:数据建模与建表实战
android·数据库·mysql
夜雪一千2 小时前
MySQL自定义函数应该如何设计
数据库·mysql
一条小小yu2 小时前
mysql的锁
数据库·mysql·oracle
fb_123452 小时前
MySQL基础核心|数据库原理+MySQL详解
数据库·mysql
‎ദ്ദിᵔ.˛.ᵔ₎2 小时前
Mysql 基本查询
数据库·mysql
-madongyu-2 小时前
GaussDB 性能调优:等待事件、慢 SQL 定位与关键参数
数据库·sql·gaussdb