天天看點

SQL Tuning Advisor使用執行個體

在oracle10g之前,想要優化一個sql語句是比較麻煩,但是在oracle10g這個版本推出的SQL Tuning Advisor這個工具,能大大減少sql調優的工作量,不過要想使用SQL Tuning Advisor,一定要保證你的優化器是CBO模式。

1.首先需要建立一個用于調優的使用者bamboo,并授予advisor給建立的使用者

SQL> create user bamboo identified by bamboo;

User created.

SQL> grant connect,resource to bamboo;

Grant succeeded.

SQL> grant advisor to bamboo;

2.建立使用者做測試的2張表,大表裡面插入500萬條資料,小表裡面插入10萬條資料,其建立方法如下

SQL> create table bigtable (id number(10),name varchar2(100));

Table created.

SQL> begin

2 for i in 1..5000000 loop

3 insert into bigtable values(i,'test'||i);

4 end loop;

5 end;

6 /

PL/SQL procedure successfully completed.

SQL> commti;

SQL> create table smalltable (id number(10),name varchar2(100));

2 for i in 1..100000 loop

3 insert into smalltable values(i,'test'||i);

3.然後對bigtable和smalltable做一個等連接配接查詢,然後跟蹤其執行計劃

SQL> select a.id,a.name,b.id,b.name from bigtable a,smalltable b where a.id=b.id and a.id=40000;

ID NAME ID NAME

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

40000 test40000 40000 test40000

Execution Plan

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

Plan hash value: 1703851322

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

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

| 0 | SELECT STATEMENT | | 839 | 106K| 3656 (5)| 00:00:44 |

|* 1 | HASH JOIN | | 839 | 106K| 3656 (5)| 00:00:44 |

|* 2 | TABLE ACCESS FULL| SMALLTABLE | 5 | 325 | 71 (3)| 00:00:01 |

|* 3 | TABLE ACCESS FULL| BIGTABLE | 173 | 11245 | 3584 (5)| 00:00:44 |

Predicate Information (identified by operation id):

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

1 - access("A"."ID"="B"."ID")

2 - filter("B"."ID"=40000)

3 - filter("A"."ID"=40000)

Note

-----

- dynamic sampling used for this statement

Statistics

9 recursive calls

0 db block gets

16151 consistent gets

11469 physical reads

0 redo size

588 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

2 sorts (memory)

0 sorts (disk)

1 rows processed

熟悉執行計劃的就可以看出,這個sql執行是很慢的,2個表都做的是全表掃描,并且其實體讀是11469,按照優化的經驗,給2個表的id建立索引,減少查詢時候的實體讀,下面我們就看看通過優化器,oracle能我們什麼樣的建議呢?

4.下面就通過DBMS_SQLTUNE包的CREATE_TUNING_TASK來建立一個優化任務,然後通過DBMS_SQLTUNE.EXECUTE_TUNING_TASK來執行調優任務,生成調優建議

SQL> DECLARE

2 my_task_name VARCHAR2(30);

3 my_sqltext CLOB;

4 BEGIN

5 my_sqltext := 'select a.id,a.name,b.id,b.name from bigtable a,smalltable b where a.id=b.id and a.id=40000';

6

7 my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(

8 sql_text => my_sqltext,

9 user_name => 'SCOTT',

10 scope => 'COMPREHENSIVE',

11 time_limit => 60,

12 task_name => 'test_sql_tuning_task1',

13 description => 'Task to tune a query');

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

15 END;

16 /

5.執行的過程中,也可以通過user_advisor_tasks或者dba_advisor_tasks來檢視調優任務執行的狀況

SQL> select task_name,ADVISOR_NAME,STATUS from user_advisor_tasks;

TASK_NAME ADVISOR_NAME STATUS

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

test_sql_tuning_task1 SQL Tuning Advisor COMPLETED

如果status是EXECUTING,則表示任務正在執行,如果為COMPLETED,則任務已經執行完畢

6.通過調用dbms_sqltune.report_tuning_task可以查詢調優的結果,不過在查詢結果之前,得設定sqlplus的環境,如果不設定,則查詢的結果出不來

SQL> set long 999999

SQL> set LONGCHUNKSIZE 999999

SQL> set serveroutput on size 999999

SQL> set linesize 200

SQL> select dbms_sqltune.report_tuning_task('test_sql_tuning_task1') from dual;

DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING_TASK1')

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

GENERAL INFORMATION SECTION

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

Tuning Task Name : test_sql_tuning_task1

Tuning Task Owner : BAMBOO

Scope : COMPREHENSIVE

Time Limit(seconds) : 60

Completion Status : COMPLETED

Started at : 10/13/2011 05:07:53

Completed at : 10/13/2011 05:08:18

Number of Statistic Findings : 2

Number of Index Findings : 1

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

Schema Name: SCOTT

SQL ID : 7arau1k5a3mv1

SQL Text : select a.id,a.name,b.id,b.name from bigtable a,smalltable b

where a.id=b.id and a.id=40000

FINDINGS SECTION (3 findings)

1- Statistics Finding

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

Table "SCOTT"."SMALLTABLE" was not analyzed.

Recommendation

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

- Consider collecting optimizer statistics for this table.

execute dbms_stats.gather_table_stats(ownname => 'SCOTT', tabname =>

'SMALLTABLE', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,

method_opt => 'FOR ALL COLUMNS SIZE AUTO');

Rationale

---------

The optimizer requires up-to-date statistics for the table in order to

select a good execution plan.

2- Statistics Finding

Table "SCOTT"."BIGTABLE" was not analyzed.

'BIGTABLE', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,

3- 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 SCOTT.IDX$$_00790001 on SCOTT.SMALLTABLE('ID');

create index SCOTT.IDX$$_00790002 on SCOTT.BIGTABLE('ID');

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

-----------

2- Using New Indices

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

Plan hash value: 3720188830

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

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

| 0 | SELECT STATEMENT | | 1 | 130 | 5 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID | BIGTABLE | 1 | 65 | 3 (0)| 00:00:01 |

| 2 | NESTED LOOPS | | 1 | 130 | 5 (0)| 00:00:01 |

| 3 | TABLE ACCESS BY INDEX ROWID| SMALLTABLE | 1 | 65 | 2 (0)| 00:00:01 |

|* 4 | INDEX RANGE SCAN | IDX$$_00790001 | 1 | | 1 (0)| 00:00:01 |

|* 5 | INDEX RANGE SCAN | IDX$$_00790002 | 1 | | 2 (0)| 00:00:01 |

4 - access("B"."ID"=40000)

5 - access("A"."ID"=40000)

從上面的結果可以看到oracle的調優顧問給我們3條建議:

(1)SCOTT.SMALLTABLE表沒有做分析,需要做一下表結構的分析,并且給出一個分析的建議,如下所示

execute dbms_stats.gather_table_stats(ownname => 'SCOTT', tabname =>

(2)SCOTT.BIGTABLE表沒有做分析,需要做一下表結構的分析,并且給出一個分析的建議,如下所示

(3)oracle建議我們在表SCOTT.SMALLTABLE,SCOTT.BIGTABLE的id列建立一個bitree索引,給的建議如下

create index SCOTT.IDX$$_00790002 on SCOTT.BIGTABLE('ID');

create index SCOTT.IDX$$_00790001 on SCOTT.SMALLTABLE('ID');

當然建立索引的名字可以改成别的名字

通過以上檢視oracle的調優顧問給的建議,基本和我們在前面給出的調優方案是一緻,是以當我們給一個大的SQL做優化的時候,可以先使用oracle調優顧問,得到一些調優方案,然後根據實際情況做一些調整就可以。

以下就是執行oracle調優顧問的建議,重新執行select a.id,a.name,b.id,b.name from bigtable a,smalltable b where a.id=b.id and a.id=40000這天語句得到的執行計劃,可以看出查詢時間和實體讀大大減少

SQL> select a.id,a.name,b.id,b.name from bigtable a,smalltable b where a.id=b.id and a.id=40000;

Plan hash value: 777647921

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

| 0 | SELECT STATEMENT | | 1 | 31 | 5 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID | BIGTABLE | 1 | 17 | 3 (0)| 00:00:01 |

| 2 | NESTED LOOPS | | 1 | 31 | 5 (0)| 00:00:01 |

| 3 | TABLE ACCESS BY INDEX ROWID| SMALLTABLE | 1 | 14 | 2 (0)| 00:00:01 |

|* 4 | INDEX RANGE SCAN | I_ID_SAMLLTABLE | 1 | | 1 (0)| 00:00:01 |

|* 5 | INDEX RANGE SCAN | I_ID_BIGTABLE | 1 | | 2 (0)| 00:00:01 |

0 recursive calls

9 consistent gets

0 physical reads

0 sorts (memory)