您的位置:首页 > 数据库 > Oracle

Oracle STA的使用

2016-06-22 16:56 417 查看
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')

------------------------------------------------
abec
----------------------------------------------------

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';
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: