前言:经常可以碰到优化sql的需求,开发人员直接扔过来一个SQL让DBA优化,然后怎么办?

当然,经验丰富的DBA可以从各种方向下手,有时通过建立正确索引即可获得很好的优化效果,但是那些复杂SQL错综复杂的表关联,却让DBA们满头大汗。

如下特别介绍一种oracle官方提供的科学优化方法STA,经过实践,不敢说此特性绝对有效,但是可以开阔思路,并且从中学到许多知识,不再用“猜”的方式去创建索引了。

SQL优化器SQL Tuning Advisor (STA),是oracle的sql优化补助工具。
其实优化sql主要有两个方案,其一是改写sql本身,改写sql需要对sql语法、数据库的执行方式都要有较好地理解。
其二就是这个STA,它属于DBMS_SQLTUNE包,它的主要作用是对于sql使用到的表创建正确的索引。

使用STA前提:

要保证优化器是CBO模式下。
show parameter OPTIMIZER_MODE
all_rows /*CBO,sql所有返回行都采用基于成本的方式运行*/
first_rows /*CBO,使用成本和试探法相结合的方法,查找一种可以最快返回前面少数行*/
first_rows_n /*CBO,全部采用基于成本的优化方法CBO,并以最快的速度,返回前N行记录*/
choose /*如果有统计信息,采用CBO,否则采用RBO*/
rule /*RBO*/ 执行DBMS_SQLTUNE包进行sql优化需要有advisor的权限:
grant advisor to scott;

如下是STA使用例子:

1.首先创建两个练习表obj与ind,仅创建表,无需创建索引:

SQL> create table obj as select * from dba_objects;
表已创建。 SQL> create table ind as select * from dba_indexes;
表已创建。 SQL> insert into obj select * from obj;
已创建 74603 行。 SQL> insert into obj select * from obj;
已创建 149206 行。 SQL> insert into obj select * from obj;
已创建 298412 行。 SQL> insert into ind select * from ind;
已创建 5134 行。 SQL> insert into ind select * from ind;
已创建 10268 行。 SQL> insert into ind select * from ind;
已创建 20536 行。

2.然后对这两个表,obj与ind进行联合查询,并通过autotrace查看其执行计划:

SQL> set timing on
SQL> set autot trace
SQL> select count(*) from obj o, ind i where o.object_name=i.index_name; 已用时间: 00: 00: 00.15 执行计划
----------------------------------------------------------
Plan hash value: 380737209 ------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 83 | | 5063 (1)| 00:01:01 |
| 1 | SORT AGGREGATE | | 1 | 83 | | | |
|* 2 | HASH JOIN | | 5861K| 463M| 1272K| 5063 (1)| 00:01:01 |
| 3 | TABLE ACCESS FULL| IND | 44789 | 743K| | 379 (1)| 00:00:05 |
| 4 | TABLE ACCESS FULL| OBJ | 577K| 36M| | 2472 (1)| 00:00:30 |
------------------------------------------------------------------------------------ Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("O"."OBJECT_NAME"="I"."INDEX_NAME") Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
9 recursive calls
4 db block gets
10406 consistent gets
0 physical reads
0 redo size
425 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

通过执行计划,可以清晰的看到,在执行以上两个表的联合查询的时候,两张表走的全表扫和hash join。


正式使用STA进行优化:
第一步:创建优化任务
通过调用函数DBMS_SQLTUNE.CREATE_TUNING_TASK来创建优化任务,调用存储过程DBMS_SQLTUNE.EXECUTE_TUNING_TASK执行该任务:

SQL> set autot off
SQL> set timing off
DECLARE
my_task_name VARCHAR2(30);
my_sqltext CLOB;
BEGIN
my_sqltext := 'select count(*) from obj o, ind i where o.object_name=i.index_name';
my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
sql_text => my_sqltext,
user_name => 'SCOTT',
scope => 'COMPREHENSIVE',
time_limit => 30,
task_name => 'tuning_sql_test',
description => 'tuning');
DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'tuning_sql_test');
END;
/
PL/SQL 过程已成功完成。

如下是参数解释:

函数CREATE_TUNING_TASK,
sql_text是需要优化的语句,
user_name是该语句通过哪个用户执行,用户名大写,
scope是优化范围(limited或comprehensive),
time_limit优化过程的时间限制,
task_name优化任务名称,
description优化任务描述。

第二步: 执行优化任务
通过调用dbms_sqltune.execute_tuning_task过程来执行前面创建好的优化任务。

SQL> exec dbms_sqltune.execute_tuning_task('tuning_sql_test');
PL/SQL 过程已成功完成。

第三步:检查优化任务的状态
通过查看user_advisor_tasks/dba_advisor_tasks视图可以查看优化任务的当前状态。

SQL> SELECT task_name,status FROM USER_ADVISOR_TASKS WHERE task_name ='tuning_sql_test';

TASK_NAME         STATUS
------------------------------ -----------
tuning_sql_test COMPLETED

步:查看优化结果
通过dbms_sqltune.report_tning_task函数可以获得优化任务的结果。

SQL> set long 999999
SQL> set serveroutput on size 999999
SQL> set line 120
SQL> select DBMS_SQLTUNE.REPORT_TUNING_TASK( 'tuning_sql_test') from dual;

如下是显示优化的结果:

DBMS_SQLTUNE.REPORT_TUNING_TASK('TUNING_SQL_TEST')
--------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name : tuning_sql_test
Tuning Task Owner : SCOTT
Workload Type : Single SQL Statement
Execution Count : 2
Current Execution : EXEC_112
Execution Type : TUNE SQL
Scope : COMPREHENSIVE
Time Limit(seconds): 30
Completion Status : COMPLETED
Started at : 08/29/2013 11:10:10
Completed at : 08/29/2013 11:10:12 -------------------------------------------------------------------------------
Schema Name: SCOTT
SQL ID : 6wruu2mxyu8g3
SQL Text : select count(*) from obj o, ind i where
o.object_name=i.index_name -------------------------------------------------------------------------------
FINDINGS SECTION (3 findings)
------------------------------------------------------------------------------- 1- Statistics Finding
---------------------
尚未分析表 "SCOTT"."IND"。 Recommendation
--------------
- 考虑收集此表的优化程序统计信息。
execute dbms_stats.gather_table_stats(ownname => 'SCOTT', tabname => 'IND', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,method_opt => 'FOR ALL COLUMNS SIZE AUTO'); Rationale
---------
为了选择好的执行计划, 优化程序需要此表的最新统计信息。 2- Statistics Finding
---------------------
尚未分析表 "SCOTT"."OBJ"。 Recommendation
--------------
- 考虑收集此表的优化程序统计信息。
execute dbms_stats.gather_table_stats(ownname => 'SCOTT', tabname => 'OBJ', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,method_opt => 'FOR ALL COLUMNS SIZE AUTO'); Rationale
---------
为了选择好的执行计划, 优化程序需要此表的最新统计信息。 3- Index Finding (see explain plans section below)
--------------------------------------------------
通过创建一个或多个索引可以改进此语句的执行计划。 Recommendation (estimated benefit: 75.74%)
------------------------------------------
- 考虑运行可以改进物理方案设计的访问指导或者创建推荐的索引。
create index SCOTT.IDX$$_00790001 on SCOTT.OBJ("OBJECT_NAME"); - 考虑运行可以改进物理方案设计的访问指导或者创建推荐的索引。
create index SCOTT.IDX$$_00790002 on SCOTT.IND("INDEX_NAME"); Rationale
---------
创建推荐的索引可以显著地改进此语句的执行计划。但是, 使用典型的 SQL 工作量运行 "访问指导"
可能比单个语句更可取。通过这种方法可以获得全面的索引建议案, 包括计算索引维护的开销和附加的空间消耗。
-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
------------------------------------------------------------------------------- 1- Original
-----------
Plan hash value: 380737209 ------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time
|
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 83 | | 5063 (1)| 00:01:01 |
| 1 | SORT AGGREGATE | | 1 | 83 | | | |
|* 2 | HASH JOIN | | 5861K| 463M| 1272K| 5063 (1)| 00:01:01 |
| 3 | TABLE ACCESS FULL| IND | 44789 | 743K| | 379 (1)| 00:00:05 |
| 4 | TABLE ACCESS FULL| OBJ | 577K| 36M| | 2472 (1)| 00:00:30 |
------------------------------------------------------------------------------------ Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("O"."OBJECT_NAME"="I"."INDEX_NAME") 2- Using New Indices
--------------------
Plan hash value: 4048334321 --------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 83 | | 1228 (2)| 00:00:15 |
| 1 | SORT AGGREGATE | | 1 | 83 | | ||
| 2 | MERGE JOIN | | 5861K| 463M| | 1228 (2)| 00:00:15 |
| 3 | INDEX FULL SCAN | IDX$$_00790001 | 577K| 36M| | 944 (1)| 00:00:12 |
|* 4 | SORT JOIN | | 44789 | 743K| 2120K| 268 (1)| 00:00:04 |
| 5 | INDEX FAST FULL SCAN| IDX$$_00790002 | 44789 | 743K| | 18 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 4 - access("O"."OBJECT_NAME"="I"."INDEX_NAME")
filter("O"."OBJECT_NAME"="I"."INDEX_NAME")

报告如上,

仔细阅读此报告,主要给出了两种建议:1.收集两张表obj与ind的统计信息;2.在这两张表上面创建相应索引。

并且特别贴心的把语句都给了出来,完全可以拿去直接运行,

更加贴心的是,报告中把优化前后的预计效果都展示了出来,完全一目了然,更加方便了DBA考虑是否进行建议优化方案。

五、删除优化任务
通过调用dbms_sqltuen.drop_tuning_task可以删除已经存在的优化任务,可以释放资源。

SQL>exec dbms_sqltune.drop_tuning_task('tuning_sql_test');

结语:如上就是SQL优化器SQL Tuning Advisor (STA)的使用方法,可能语法有些复杂,但是确实给优化的工作带来了很大帮助,经常使用多加练习即可熟练。

[terry笔记]Oracle SQL 优化之sql tuning advisor (STA)的更多相关文章

  1. 【转】使用SQL Tuning Advisor STA优化SQL

    SQL优化器(SQL Tuning Advisor STA)是Oracle10g中推出的帮助DBA优化工具,它的特点是简单.智能,DBA值需要调用函数就可以给出一个性能很差的语句的优化结果.下面介绍一 ...

  2. 如何用 SQL Tuning Advisor (STA) 优化SQL语句

    在Oracle10g之前,优化SQL是个比较费力的技术活,不停的分析执行计划,加hint,分析统计信息等等.在10g中,Oracle推出了自己的SQL优化辅助工具: SQL优化器(SQL Tuning ...

  3. Oracle性能优化之SQL语句

    1.SQL语句执行过程 1.1 SQL语句的执行步骤 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义. 2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限. ...

  4. ORACLE性能优化之SQL语句优化

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   操作环境:AIX +11g+PLSQL 包含以下内容: 1.  SQL语句执行过程 2.  优化器及执行计划 3.  合 ...

  5. SQL优化之SQL 进阶技巧(上)

    由于工作需要,最近做了很多 BI 取数的工作,需要用到一些比较高级的 SQL 技巧,总结了一下工作中用到的一些比较骚的进阶技巧,特此记录一下,以方便自己查阅,主要目录如下: SQL 的书写规范 SQL ...

  6. SQL优化之SQL 进阶技巧(下)

    上文( SQL优化之SQL 进阶技巧(上) )我们简述了 SQL 的一些进阶技巧,一些朋友觉得不过瘾,我们继续来下篇,再送你 10 个技巧 一. 使用延迟查询优化 limit [offset], [r ...

  7. Oracle自带工具sql优化集-SQL Tuning Advisor (使用心得体会)

    如何有效的诊断和监控高负载的SQL对于DBA来说并非是件容易的事情,对SQL语句手工调优需要很多的经验和技巧, 结合个人经验常见如下问题:          . 对SQL语句本身进行优化以便获得更优的 ...

  8. oracle11g中SQL优化(SQL TUNING)新特性之SQL Plan Management(SPM)

    1.   简介 Oracle Database11gR1引进了SQL PlanManagement(简称SPM),一套允许DBA捕获和保持任意SQL语句执行计划最优的新工具,这样,限制了刷新优化器统计 ...

  9. SQL优化(SQL TUNING)可大幅提升性能的实战技巧之一——让计划沿着索引跑

    我们进行SQL优化时,经常会碰到对大量数据集进行排序,然后从排序后的集合取前部分结果的需求,这种情况下,当我们按照常规思路去写SQL时,系统会先读取过滤获得所有集合,然后进行排序,再从排序结果取出极少 ...

随机推荐

  1. CF786A - Berzerk

    /* CF786A - Berzerk http://codeforces.com/contest/786/problem/A 博弈论 直接搜出NP状态图.记得要记忆化剪枝. * */ #includ ...

  2. hdu 4607 树形dp 树的直径

    题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n)个点,至少需要走多少距离(每条边的距离是1): 思路:树形dp求树的直径r: a:若k<=r+1 ...

  3. spring bean的作用域和自动装配

    1 Bean的作用域 l  singleton单列:整个容器中只有一个对象实例,每次去访问都是访问同一个对象  默认是单列 l  prototype原型: 每次获取bean都产生一个新的对象,比如Ac ...

  4. [Design]Adobe CS6 2%错误问题

    错误描述:FATAL: Payload '{3F023875-4A52-4605-9DB6-A88D4A813E8D} Camera Profiles Installer 6.0.98.0' info ...

  5. 让VMware ESXi虚拟交换机支持VLAN

    眼下虚拟化应用比較广泛,通常情况下.一台物理主机在安装VMware ESXi或Hyper-V虚拟机软件后.能够在一台物理主机上创建多个虚拟机,而且创建的每一个虚拟机能够像原来的物理一样对外提供服务,这 ...

  6. c/c++中sleep()函数毫秒级的实现

    近期看到好多人在问.c/c++中的sleep函数是秒级的,能不能实现毫秒级的呢?当然非常easy.我的写法例如以下 #include <stdio.h> #include <sys/ ...

  7. android开发一些小bug

    1.一定要注意findViewId这种方法,尤其是含有多个同样的R.id的名字时,debug时不会当场报错.但随后会报空指针错误 2.List转换为Array能够这样处理: ArrayList< ...

  8. css sprite的实现

    css sprite 为什么使用css sprite? 网页上的非常多静态小图片在载入时须要大量http请求,添加了响应时间.(哈哈.雅虎34条优化法则的第一条啊) css的background-po ...

  9. iOS-UIApplication详解

    UIApplication简介 UIApplication对象是应用程序的象征. 每一个应用程序都有自己的UIApplication对象,而且是单例. 一个iOS程序启动后创建的第一个对象就是UIAp ...

  10. php生产随机数

    php生产随机数 要求 生产三种随机数 1.全数字 2.全字母,大小写 3.数字和大小写字母 代码 <?php class RandString{ //这个属性表示我们随机数的长度,也就是个数 ...