Oracle STA的使用

Oracle 10g之后的优化器支持两种模式,一个是normal模式,一个是tuning模式。在大多数情况下,优化器处于normal模式。基于CBO的normal模式只考虑很小部分的执行计划集合用于选择哪个执行计划,因为它需要在尽可能短的时间,通常是几秒或毫秒级来对当前的SQL语句进行解析并生成执行计划。因此并不能保证SQL语句每次都是使用最佳的执行计划。而tuning模式则将高负载的SQL语句直接扔给优化器,优化器来自动对其进行详细的分析,调试并给出建议,这就是Oracle 提供的Automatic Tuning Optimizer,即自动调整优化器。Oracle 自动调整优化器通过SQL调优建议器(SQL tuning advisor)来体现。 




1、SQL tuning的基本步骤
a、鉴别需要调整的高负载SQL或者Top SQL
b、寻找可改进的执行计划
c、实施能够改进的执行计划以提高SQL效率


2、如何tuning SQL
a、检查是否为优化器设置了合理的参数(optimizer_mode,optimizer_index_caching,optimizer_index_cost_adj,以及相关cache size)
b、检查SQL语句所涉及的对象是否存在过时的统计信息或者倾斜列是否缺少直方图等
c、通过添加提示来引导SQL语句使用正确的访问路径,以及连接方式等
d、重构等价的SQL语句以使得SQL更高效(如最小化基表及中间结果集,避免列运算,列上的函数,null值,不等运算使得索引失效)
e、添加合理的索引或物化视图以及移除冗余索引,分散I/O等


3、Automatic Tuning Optimizer 做什么?
a、分析统计信息
优化器执行计划产生期间记录当前SQL语句涉及对象的统计信息的类型以及哪些被使用或哪些是需要的
当统计信息记录完成后自动调整优化器会比对与查询相关的这些对象的统计信息是否可用或过时或非均衡列缺少直方图等
针对上述的操作之后得到哪些对象没有统计信息以及哪些对象缺少统计信息以及额外的统计信息用于生成report 
b、分析访问路径
优化器会分析当前SQL所使用的访问路径是否合理,也就是分析基于表的访问方式,如全表扫描,索引扫描等
自动调整优化器会基于谓词尝试假设性的推断来创建合理的索引,也就是建议通过添加或修改相应的索引来提高性能
c、SQL结构分析
优化器会建议对于一些具有较大影响的SQL语句作结构性调整及转换(基于内部规则),如未嵌套的子查询,重写物化视图,视图合并等
基于语法以及语义结构的分析与调整,如谓词列上的运算,UNION与UNION ALL的使用,NOT IN, NOT EXIST之间替换等
对中间结果集以及连接方式等实现一些预估的分析
d、SQL profiling
SQL profiling 内置于优化器,就是一个剖析工具,基于上述得到的信息对当前的SQL进行剖析,以检查出导致性能糟糕的故障点
所有上述分析得到的结果以及辅助信息最后以sql profile的形式表现出来,供用户来判断是否接受
当用户接受这些profile,下次处于normal模式时,相同的sql语句会使用这个profile
可以对profile进行启用,停用,以及修改,因此即使表发生较大的变化,profile依旧能使得SQL受益


4、STA可tuning的方式
STA提供OEM图形界面以及API方式进行tuning,本文主要描述API即dbms_sqltune.create_tuning_task方式
下面是可被create_tuning_task接受的API方式
a、直接提供SQL语句文本
b、引用共享池中的SQL语句(sql_id)
c、引用awr自动工作负载中的SQL语句(sql_id)

d、建议SQL调优集(批量tuning)



【实例】

查看版本
SQL> select * from v$version where rownum<2;


BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production


创建演示表
SQL> CREATE TABLE t NOLOGGING AS SELECT * FROM dba_source, (SELECT * FROM DUAL CONNECT BY ROWNUM < 5);
SQL> execute dbms_stats.gather_table_stats(ownname => 'SYS', tabname => 'T',estimate_percent => 50);




查看SQL执行计划
SQL> explain plan for SELECT COUNT (*) FROM t a WHERE a.ROWID > (SELECT MIN (b.ROWID) FROM t b  WHERE a.owner = b.owner AND a.name = b.name AND a.TYPE = b.TYPE AND a.line = b.line);
SQL> select * from table(dbms_xplan.display());
-----------------------------------------------------------------------------------------
| Id  | Operation             | Name    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |         |     1 |   134 |       | 44522   (1)| 00:08:55 |
|   1 |  SORT AGGREGATE       |         |     1 |   134 |       |            |          |
|*  2 |   HASH JOIN           |         |   138K|    17M|   208M| 44522   (1)| 00:08:55 |
|   3 |    VIEW               | VW_SQ_1 |  2764K|   176M|       | 11960   (1)| 00:02:24 |
|   4 |     HASH GROUP BY     |         |  2764K|   176M|       | 11960   (1)| 00:02:24 |
|   5 |      TABLE ACCESS FULL| T       |  2764K|   176M|       | 11887   (1)| 00:02:23 |
|   6 |    TABLE ACCESS FULL  | T       |  2764K|   176M|       | 11887   (1)| 00:02:23 |
-----------------------------------------------------------------------------------------


下面就用DBMS_SQLTUNE优化该SQL
--1.如无权限,需要赋予用户ADVISOR权限
grant ADVISOR  to test;


--2.创建sql tuning任务
DECLARE
 my_task_name VARCHAR2(30);
 my_sqltext   CLOB;
BEGIN
 --my_sqltext := 'select * from emp where ename= :name and DEPTNO= :deptno';
 my_sqltext := 'SELECT COUNT (*) FROM t a WHERE a.ROWID > (SELECT MIN (b.ROWID) FROM t b  WHERE a.owner = b.owner AND a.name = b.name AND a.TYPE = b.TYPE AND a.line = b.line)';
 my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
 sql_text    => my_sqltext,
 --bind_list   => sql_binds(anydata.convertvarchar2(10),anydata.convertnumber(2)), 
 --user_name   => 'TEST',
 scope       => 'COMPREHENSIVE',
 time_limit  => 60,
 task_name   => 'test_sql_tuning', 
 description => 'Task to tune a query on table T');
END;
/


参数说明:
bind_list:多个绑定变量以','逗号分隔。参数值一定要根据绑定变量对应的列的类型书写.
如:emp.ename类型是VARCHAR2(10),那么就要写成 bind_list    =>sql_binds(anydata.convertvarchar2(10)),
time_limit:执行的最长时间,默认是60。
scope:
LIMITED,用大概1秒时间去优化SQL语句,但是并不进行SQL Profiling分析。
COMPREHENSIVE,进行全面分析,包含SQL Profiling分析;比LIMITED用时更长。


--3.查看任务 
SQL> SELECT OWNER,TASK_ID,TASK_NAME,STATUS FROM DBA_ADVISOR_LOG WHERE TASK_NAME='test_sql_tuning';


OWNER         TASK_ID TASK_NAME            STATUS
---------- ---------- -------------------- -----------
SYS              8674 test_sql_tuning      INITIAL




--4.执行sql tuning任务
BEGIN
  DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'test_sql_tuning' );
END;
/


--5.查看SQL TUNING状态
SQL> SELECT status FROM   USER_ADVISOR_TASKS WHERE  task_name = 'test_sql_tuning';


STATUS
-----------
COMPLETED


--6.展示sql tunning结果
SET LONG 10000
SET LONGCHUNKSIZE 1000
SET LINESIZE 100
SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('test_sql_tuning') FROM   DUAL;


结果中会给出一些建议,比如建议我们锁定SQL profile或者创建索引等:
SQL> SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('test_sql_tuning') FROM   DUAL;


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : test_sql_tuning
Tuning Task Owner  : SYS
Workload Type      : Single SQL Statement
Execution Count    : 2
Current Execution  : EXEC_9010
Execution Type     : TUNE SQL
Scope              : COMPREHENSIVE
Time Limit(seconds): 60
Completion Status  : COMPLETED


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------
Started at         : 04/20/2016 09:19:33
Completed at       : 04/20/2016 09:20:10


-------------------------------------------------------------------------------
Schema Name: SYS
SQL ID     : 5ukykzs1hvk7b
SQL Text   : SELECT COUNT (*) FROM t a WHERE a.ROWID > (SELECT MIN (b.ROWID)
             FROM t b  WHERE a.owner = b.owner AND a.name = b.name AND a.TYPE
             = b.TYPE AND a.line = b.line)


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


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------


1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
  A potentially better execution plan was found for this statement.


  Recommendation (estimated benefit: 38.69%)
  ------------------------------------------
  - Consider accepting the recommended SQL profile.
    execute dbms_sqltune.accept_sql_profile(task_name => 'test_sql_tuning',


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------
            task_owner => 'SYS', replace => TRUE);


-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------


1- Original With Adjusted Cost
------------------------------
Plan hash value: 2929971977


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


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------
| Id  | Operation              | Name      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |           |     1 |       |       |   129K  (1)| 00:26:00 |
|   1 |  SORT AGGREGATE        |           |     1 |       |       |            |          |
|   2 |   VIEW                 | VM_NWVW_2 |   491K|       |       |   129K  (1)| 00:26:00 |
|*  3 |    FILTER              |           |       |       |       |            |          |
|   4 |     HASH GROUP BY      |           |   491K|    45M|  1067M|   129K  (1)| 00:26:00 |
|*  5 |      HASH JOIN         |           |  9837K|   919M|   148M| 45513   (1)| 00:09:07 |
|   6 |       TABLE ACCESS FULL| T         |  2549K|   119M|       | 11886   (1)| 00:02:23 |
|   7 |       TABLE ACCESS FULL| T         |  2549K|   119M|       | 11886   (1)| 00:02:23 |
--------------------------------------------------------------------------------------------


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------


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


   3 - filter("A".ROWID>MIN("B".ROWID))
   5 - access("A"."OWNER"="B"."OWNER" AND "A"."NAME"="B"."NAME" AND
              "A"."TYPE"="B"."TYPE" AND "A"."LINE"="B"."LINE")


2- Using SQL Profile
--------------------
Plan hash value: 1985065416


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------


-----------------------------------------------------------------------------------------
| Id  | Operation             | Name    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |         |     1 |   116 |       | 79651   (1)| 00:15:56 |
|   1 |  SORT AGGREGATE       |         |     1 |   116 |       |            |          |
|*  2 |   HASH JOIN           |         |  1647K|   182M|   148M| 79651   (1)| 00:15:56 |
|   3 |    TABLE ACCESS FULL  | T       |  2549K|   119M|       | 11886   (1)| 00:02:23 |
|   4 |    VIEW               | VW_SQ_1 |  2549K|   162M|       | 42760   (1)| 00:08:34 |
|   5 |     HASH GROUP BY     |         |  2549K|   119M|   156M| 42760   (1)| 00:08:34 |
|   6 |      TABLE ACCESS FULL| T       |  2549K|   119M|       | 11886   (1)| 00:02:23 |


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------


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


   2 - access("A"."OWNER"="ITEM_1" AND "A"."NAME"="ITEM_2" AND
              "A"."TYPE"="ITEM_3" AND "A"."LINE"="ITEM_4")
       filter("A".ROWID>"MIN(B.ROWID)")


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




DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING')
----------------------------------------------------------------------------------------------------




--7.完成后删除sql tunning任务
EXEC DBMS_SQLTUNE.DROP_TUNING_TASK('test_sql_tuning');


--8.查看SQL Tuning Advisor的进展(task执行很久)
col opname for a20
col ADVISOR_NAME for a20
SELECT SID,SERIAL#,USERNAME,OPNAME,ADVISOR_NAME,TARGET_DESC,START_TIME SOFAR, TOTALWORK 
FROM   V$ADVISOR_PROGRESS 
WHERE  USERNAME = 'SYS';


你可能感兴趣的:(Oracle STA的使用)