SQL Profile介紹

什麼是SQL Profile

 

       SQL Profile在性能優化中佔有一個重要的位置。

       MOS裏這麼描述SQL Profile:

       SQL Profile是10g中的新特性,作爲自動SQL調整過程的一部分,由Oracle企業管理器來管理。除了OEM,SQL Profile可以通過DBMS_SQLTUNE包來進行管理。

       查詢優化器有時候會因爲缺乏足夠的信息,而對一條SQL語句做出錯誤的估計,生成糟糕的執行計劃。而自動SQL調整通過SQL概要分析來解決這個問題,自動調整優化器會生成這條SQL語句的一個概要,稱作SQL Profile。它由針對這條語句的一些輔助統計信息組成,通過採樣和局部執行技術來確認,必要的話,會調整執行計劃中的估計值。在SQL概要分析中,自動調整優化器還可以通過一條SQL語句的執行歷史信息來設置合適的優化器參數,比如將OPTIMIZER_MODE參數由ALL_ROWS改爲FIRST_ROWS。

       換句話說,SQL概要是一個對象,它包含了可以幫助查詢優化器爲一個特定的SQL語句找到高效執行計劃的信息。這些信息包括執行環境、對象統計和對查詢優化器所做評估的修正信息。它的最大優點之一就是在不修改SQL語句和會話執行環境的情況下影響查詢優化器的決定。(《Oracle性能診斷藝術》)

       SQL Profile中包含的並非單個執行計劃的信息,必須注意的是,SQL Profile不會固定一個SQL語句的執行計劃。當表的數據增長或者索引創建、刪除,使用同一個SQL Profile的執行計劃可能會改變,而儲存在SQL Profile中的信息會繼續起作用。然而,經過一段很長的時間之後,它的信息有可能會過時,需要重新生成。

       SQL Profile的作用範圍由CATEGORY屬性來控制,這個屬性決定了哪些用戶會話可以應用這個概要。你可以從DBA_SQL_PROFILES中的CATEGORY字段來查看這個屬性。默認情況下,所有概要文件都創建爲DEFAULT範疇,這意味着所有SQLTUNE_CATEGORY初始化參數爲DEFAULT的用戶會話都可以使用這個概要。你可以修改這個屬性,比如將其改爲DEV,則SQLTUNE_GATEGORY參數爲DEV的用戶會話才能使用它,利用這個功能,你可以在一個受限制的環境中來測試一個SQL Profile。

       SQL Profile可以作用在如下表達式中:SELECT; UPDATE; INSERT(在包含SELECT子句的情況下); DELETE; CREATE TABLE(包含SELECT子句的情況下); MERGE(UPDATE或INSERT操作)。

 

Oracle執行SQL語句的步驟如下:

1. 用戶傳送要執行的SQL語句給SQL引擎

2. SQL引擎要求查詢優化器提供執行計劃

3. 查詢優化取得系統統計信息、SQL語句引用對象的對象統計信息、SQL概要和構成執行環境的初始化參數

4. 查詢優化器分析SQL語句併產生執行計劃

5. 將執行計劃傳遞給SQL引擎

6. SQL引擎執行SQL語句



SQL Profile的管理


       SQL Profile可以由OEM來管理,也可以通過DBMS_SQLTUNE包來手動使用。


使用OEM時步驟如下:

1. 在Performance頁面,點擊Top Activity。出現了Top Activity頁面

2. 在Top SQL下面,點擊正在使用SQL Profile的SQL表達式的SQL ID鏈接,會出現一個SQL Details頁面

3. 點擊Plan Control選項卡,在SQL Profiles and Outlines下面會顯示一個SQL profile的列表

4. 選擇你想要管理的SQL Profile,可以做如下操作:啓用或禁用、移除

5. 會出現一個確認的頁面,點擊Yes繼續,No取消


如果使用DBMS_SQLTUNE包,你需要CREATE ANY SQL_PROFILE、DROP ANY SQL_PROFILE還有ALTER ANY SQL_PROFILE的系統權限。

使用DBMS_SQLTUNE.ACCEPT_SQL_PROFILE過程來接受並創建SQL Tuning Advisor建議的SQL Profile

DECLARE
my_sqlprofile_name VARCHAR2(30);
BEGIN
my_sqlprofile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE ( 
task_name => 'my_sql_tuning_task',
name => 'my_sql_profile');
END;
my_sql_tuning_task是SQL調整目標的名稱。
這個過程的傳入參數中有一個可選參數force_match,默認爲FALSE。當設置爲FALSE時,不區分空白和大小寫,爲TRUE時,空白、大小寫和字面量都不區分。通過企業管理器來接受SQL概要時,這個參數在ORACLE11g中纔可以設置。

修改SQL Profile,可以修改STATUS、NAME、DESCRIPTION和CATEGORY屬性

BEGIN
DBMS_SQLTUNE.ALTER_SQL_PROFILE(
name => 'my_sql_profile', 
attribute_name => 'STATUS', 
value => 'DISABLED');
END;
/

刪除SQL Profile

begin
DBMS_SQLTUNE.DROP_SQL_PROFILE(name => 'my_sql_profile');
end;
/

對我們來說,重點在於創建SQL Profile時的my_sql_tuning_task上,它通過函數create_tuning_task來創建,執行這個函數需要傳遞下面的參數之一:SQL語句文本、存儲在共享池中的SQL語句引用(sql_id)、存儲在自動工作量資料庫中的SQL語句引用(sql_id)、SQL調優集名稱。
比如利用sql_id來創建tuning_task,我們可以這麼運行
declare
tuning_task varchar2(30);
begin
  tuning_task:=dbms_sqltune.create_tuning_task(sql_id => 'bfb9vn0gh3z0t');
  dbms_output.put_line(tuning_task);
end;
記下這個tuning_task,用於後面的過程來使用

什麼是SQL調優集(tuning set)?簡單來講,SQL調優集是存儲一系列SQL語句及其相關信息的對象集合,這些信息包括執行環境、運行統計和可選的執行計劃。


下面引用MOS提供的一個示例來演示一下這個過程



示例


SESSION1--SCOTT

創建表,填充數據,然後創建索引和採集統計信息。使用no_index提示來執行查詢,使用全表掃描
SQL> create table test (n number );
Table created.

SQL> declare
          begin
           for i in 1 .. 10000 loop
               insert into test values(i);
               commit;
           end loop;
          end;
/
PL/SQL procedure successfully completed.

SQL> create index test_idx on test(n);
Index created.

SQL> exec dbms_stats.gather_table_stats('','TEST');
PL/SQL procedure successfully completed.

set autotrace on
select /*+ no_index(test test_idx) */ * from test where n=1


--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows   | Bytes | Cost (%CPU)| Time    | 
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     4 |     5   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST |     1 |     4 |     5   (0)| 00:00:01 | 
-------------------------------------------------------------------------- 


SESSION2--SYS


創建並執行tuning task,並運行report tuning task,採用建議的SQL Profile

declare
  my_task_name VARCHAR2(30);
  my_sqltext CLOB;
  begin
     my_sqltext := 'select /*+ no_index(test test_idx) */ * from test where n=1';
     my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
     sql_text => my_sqltext,
     user_name => 'SCOTT',
     scope => 'COMPREHENSIVE',
     time_limit => 60,
     task_name => 'my_sql_tuning_task_2',
     description => 'Task to tune a query on a specified table');
end;
/
PL/SQL procedure successfully completed.

begin
DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'my_sql_tuning_task_2');
end;
/
PL/SQL procedure successfully completed.

set long 1000
set longchunksize 1000
set linesize 100
SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK( 'my_sql_tuning_task_2') from DUAL;

DBMS_SQLTUNE.REPORT_TUNING_TASK('MY_SQL_TUNING_TASK_2') 
-------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : my_sql_tuning_task_2
Tuning Task Owner  : SYS  
Workload Type      : Single SQL Statement 
Scope              : COMPREHENSIVE 
Time Limit(seconds): 60 
Completion Status  : COMPLETED 
Started at         : 10/26/2011 15:07:04
Completed at       : 10/26/2011 15:07:08

DBMS_SQLTUNE.REPORT_TUNING_TASK('MY_SQL_TUNING_TASK_2') 
----------------------------------------------------------------------------------
---------------------------------------------------------------------------------- 
Schema Name: SCOTT
SQL ID     : d4wgpc5g0s0vu
SQL Text   : select /*+ no_index(test test_idx) */ * from test where n=1
------------------------------------------------------------------------------- 
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------
1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
DBMS_SQLTUNE.REPORT_TUNING_TASK('MY_SQL_TUNING_TASK_2')
-------------------------------------------------------------------------------------  
A potentially better execution plan was found for this statement.
Recommendation (estimated benefit: 90.95%)
------------------------------------------
- Consider accepting the recommended SQL profile.
execute dbms_sqltune.accept_sql_profile(task_name =>
             'my_sql_tuning_task_2', task_owner => 'SYS', replace => TRUE);

DECLARE
my_sqlprofile_name VARCHAR2(30);
begin
my_sqlprofile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (
task_name => 'my_sql_tuning_task_2',
name => 'my_sql_profile');
end;
/

PL/SQL procedure successfully completed.

SESSION1--SCOTT


重新執行查詢,即使使用了no_index提示,索引也會被使用

注意,在執行計劃中,我們會看到SQL profile "my_sql_profile" used for this statement

SQL> set autotrace on
SQL> select /*+ no_index(test test_idx) */ * from test where n=1;


Execution Plan      
-------------------------------------------------------------------------
Plan hash value: 1416057887                                                                  
----------------------------------------------------------------------------- 
| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     | 
----------------------------------------------------------------------------- 
|   0 | SELECT STATEMENT |          |     1 |     4 |     1   (0)| 00:00:01 | 
|*  1 |  INDEX RANGE SCAN| TEST_IDX |     1 |     4 |     1   (0)| 00:00:01 | 
-----------------------------------------------------------------------------                                                                               
Predicate Information (identified by operation id):
---------------------------------------------------  
   1 - access("N"=1)
---------------        
Note 
----- 
   - SQL profile "my_sql_profile" used for this statement 

 
由這個例子我們可以發現,在必要情況下,SQL Profile可以讓hint失效
 
 
如何爲每個tuning set 產生一個報告

SELECT 'SELECT d.id , d.owner , d.description , d.created , d.last_modified , d.statement_count, ss.* FROM TABLE(DBMS_SQLTUNE.select_sqlset ('''||name||''')) ss, dba_sqlset d WHERE d.name='''||name||''';'
FROM dba_sqlset d
ORDER BY d.last_modified DESC



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