使用SQL Tuning Advisor (STA) 優化SQL語句

在Oracle10g之前,優化SQL是個比較費力的技術活,不停的分析執行計劃,加hint,分析統計信息等等。在10g中,Oracle推出了自己的SQL優化輔助工具: SQL優化器(SQL Tuning Advisor STA),它是新的DBMS_SQLTUNE包。使用STA一定要保證優化器是CBO模式下。

執行DBMS_SQLTUNE包進行sql優化需要有advisor的權限:

SQL> create user dave identified by dave;

用戶已創建。

SQL> grant connect,resource to dave;

授權成功。

SQL> grant advisor to dave;

授權成功。

下面簡單介紹一下如何優化一條找到的問題語句。

create table bigtab as select rownum as "id",a.from sys.all_objects a;

create table smalltab as select rownum as "id", a.FROM sys.all_tables a;

然後多運行幾次下面的腳本,增加表裏的數據:

insert into bigtab select rownum as "id",a.from sys.all_objects a;

insert into smalltab  select rownum as "id", a.FROM sys.all_tables a;

這裏創建一張大表和一張小表,並且都沒有索引,下面執行一個查詢:

SQL> set timing on

SQL> set autot on

SQL> select count(*) from bigtab a, smalltab b where a.object_name=b.table_name;

  COUNT(*)

----------

   2141537

已用時間:  00: 00: 20.05

執行計劃

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

Plan hash value: 3089226980

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

| Id  | Operation           | Name     | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT    |          |     1 |    45 |  3146   (1)| 00:00:38 |

|   1 |  SORT AGGREGATE     |          |     1 |    45 |            |          |

|*  2 |   HASH JOIN         |          |   447K|    19M|  3146   (1)| 00:00:38 |

|   3 |    TABLE ACCESS FULL| SMALLTAB | 27327 |   533K|   264   (1)| 00:00:04 |

|   4 |    TABLE ACCESS FULL| BIGTAB   |   712K|    16M|  2878   (1)| 00:00:35 |

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

Predicate Information (identified by operation id):

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

   2 - access("A"."OBJECT_NAME"="B"."TABLE_NAME")

統計信息

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

          0  recursive calls

          0  db block gets

      31149  consistent gets

      21058  physical reads

          0  redo size

        426  bytes sent via SQL*Net to client

        416  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

第一步:創建優化任務

通過調用函數CREATE_TUNING_TASK來創建優化任務,調用存儲過程EXECUTE_TUNING_TASK執行該任務:

SQL> set autot off

SQL> set timing off

SQL> DECLARE

  2    my_task_name VARCHAR2(30);

  3    my_sqltext   CLOB;

  4  BEGIN

  5    my_sqltext := 'select count(*) from bigtab a, smalltab b where a.object_name=b.table_name';

  6    my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(

  7            sql_text    => my_sqltext,

  8            user_name   => 'DAVE',   -- 注意是大寫,不然會報錯,用戶無效

  9            scope       => 'COMPREHENSIVE',

10            time_limit  => 60,

11            task_name   => 'tuning_sql_test',

12            description => 'Task to tune a query on a specified table');

13

14    DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'tuning_sql_test');

15  END;

16  /

 

PL/SQL procedure successfully completed.

在函數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 LINESIZE 100

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                 : DEMO

Scope                             : COMPREHENSIVE

Time Limit(seconds)               : 60

Completion Status                 : COMPLETED

Started at                        : 5/28/2010 13:16:43

Completed at                      : 5/28/2010 13:16:44

Number of Index Findings          : 1

 

Schema Name: DEMO

SQL ID     : 6p64dnnsqf9pm

SQL Text   : select count(*) from bigtab a, smalltab b where

             a.object_name=b.table_name

 

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

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: 100%)

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

  - Consider running the Access Advisor to improve the physical schema design

    or creating the recommended index.

    create index DEMO.IDX$$_06C50001 on SYS.SMALLTAB('TABLE_NAME');

 

  - Consider running the Access Advisor to improve the physical schema design

    or creating the recommended index.

    create index DEMO.IDX$$_06C50002 on SYS.BIGTAB('OBJECT_NAME');

 

  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.

 

 

EXPLAIN PLANS SECTION

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

1- Original

-----------

Plan hash value: 3089226980

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

| Id  | Operation           | Name     | Rows  | Bytes | Cost (%CPU)| Time     |

 

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

|   0 | SELECT STATEMENT    |          |     1 |    36 |  3550   (2)| 00:00:43 |

|   1 |  SORT AGGREGATE     |          |     1 |    36 |            |          |

|*  2 |   HASH JOIN         |          |   155K|  5462K|  3550   (2)| 00:00:43 |

|   3 |    TABLE ACCESS FULL| SMALLTAB |  1223 | 22014 |    11   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| BIGTAB   |  1205K|    20M|  3526   (1)| 00:00:43 |

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

Predicate Information (identified by operation id):

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

   2 - access("A"."OBJECT_NAME"="B"."TABLE_NAME")

2- Using New Indices

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

Plan hash value: 494801882

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

| Id  | Operation              | Name           | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT       |                |     1 |    36 |  1108   (3)| 00:00:14 |

|   1 |  SORT AGGREGATE        |                |     1 |    36 |            |        |

|*  2 |   HASH JOIN            |                |   155K|  5462K|  1108   (3)| 00:00:14 |

|   3 |    INDEX FAST FULL SCAN| IDX$$_06C50001 |  1223 | 22014 |     3   (0)| 00:00:01 |

|   4 |    INDEX FAST FULL SCAN| IDX$$_06C50002 |  1205K|    20M|  1093   (2)| 00:00:14 |

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

Predicate Information (identified by operation id):

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

   2 - access("A"."OBJECT_NAME"="B"."TABLE_NAME")

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

看一下這個優化建議報告:

第一部分是關於這次優化任務的基本信息:如任務名稱、執行時間、範圍、涉及到的語句等等。

第二部分是關於這次優化任務的所找到的問題以及給出的優化建議。前面先給出了問題描述:可以通過建立更多的所引來提高性能;然後是建議的具體內容:在表smalltab的字段table_name上創建索引,在表bigtab的字段object_name上創建索引;最後是相關注意事項:此次優化雖然給出了創建索引的建議,但是最好通過SQL訪問建議器(SQL Access Advisor SAA)結合整個數據庫的工作量來深入分析,那樣就能給出考慮了索引維護和空間消耗等因素的更加合理的建議。

最後,報告還給出了原有的查詢計劃,以及採用優化建議以後的查詢計劃的對比。可以看出COST值大大下降。

五、刪除優化任務

通過調用dbms_sqltuen.drop_tuning_task可以刪除已經存在的優化任務

SQL>exec dbms_sqltune.drop_tuning_task('tuning_sql_test');
PL/SQL procedure successfully completed.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章