溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

通過案例學調優之--SQL Profile

發布時間:2020-07-01 06:40:28 來源:網絡 閱讀:3034 作者:客居天涯 欄目:關系型數據庫

通過案例學調優之--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的用戶會話都可以使用這個概要。你可以修改這個屬性,比如將其改為SCO,則SQLTUNE_GATEGORY參數為SCO的用戶會話才能使用它,利用這個功能,你可以在一個受限制的環境中來測試一個SQL Profile。

16:42:03 SYS@ prod >desc dba_sql_profiles
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 NAME                                                              NOT NULL VARCHAR2(30)
 CATEGORY                                                          NOT NULL VARCHAR2(30)
 SIGNATURE                                                         NOT NULL NUMBER
 SQL_TEXT                                                          NOT NULL CLOB
 CREATED                                                           NOT NULL TIMESTAMP(6)
 LAST_MODIFIED                                                              TIMESTAMP(6)
 DESCRIPTION                                                                VARCHAR2(500)
 TYPE                                                                       VARCHAR2(7)
 STATUS                                                                     VARCHAR2(8)
 FORCE_MATCHING                                                             VARCHAR2(3)
 TASK_ID                                                                    NUMBER
 TASK_EXEC_NAME                                                             VARCHAR2(30)
 TASK_OBJ_ID                                                                NUMBER
 TASK_FND_ID                                                                NUMBER
 TASK_REC_ID                                                                NUMBER
 
16:50:43 SYS@ prod >select name, CATEGORY,sql_text,status from dba_sql_profiles;
no rows selected

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

二、SQL Profile的管理

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

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

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

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

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

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

6. SQL引擎執行SQL語句

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

(1)、使用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取消

通過案例學調優之--SQL Profile

通過案例學調優之--SQL Profile

(2)、使用DBMS_SQLTUNE包

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

1)、創建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;

這個過程的傳入參數中有一個可選參數force_match,默認為FALSE。當設置為FALSE時,不區分空白和大小寫,為TRUE時,空白、大小寫和字面量都不區分。通過企業管理器來接受SQL概要時,這個參數在ORACLE11g中才可以設置。

2)、修改SQL Profile

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

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

3)、刪除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 => 'bfb9vn0gh4z0t'); 
  dbms_output.put_line(tuning_task); 
end;

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

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

案例分析:

1、scott用戶執行sql
17:19:56 SCOTT@ prod >create table test (n number);
Table created.

17:20:16 SCOTT@ prod >begin
17:20:24   2  for i in 1..100000 loop
17:20:36   3  insert into test values (i);
17:20:47   4  commit;
17:20:49   5  end loop;
17:20:52   6  end;
17:20:53   7  /
PL/SQL procedure successfully completed.

17:22:02 SCOTT@ prod >create index test_ind on test(n);
Index created.

17:22:55 SCOTT@ prod >exec dbms_stats.gather_table_stats(user,'TEST' ,cascade=>true);
PL/SQL procedure successfully completed.

17:23:15 SCOTT@ prod >set autotrace on
17:23:43 SCOTT@ prod >select * from test where n=100;
         N
----------
       100
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 3357096749
-----------------------------------------------------------------------------
| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |          |     1 |     5 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TEST_IND |     1 |     5 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("N"=100)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        415  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
          
對此sql建立sql profile:
17:24:02 SCOTT@ prod >select /*+ no_index(test,test_ind) */ * from test where n=100;
         N
----------
       100
Elapsed: 00:00:00.01
Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     5 |    69   (2)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST |     1 |     5 |    69   (2)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("N"=100)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        191  consistent gets
          0  physical reads
          0  redo size
        415  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
          
2、通過sys用戶建立sql profile(使用dbms_sqltune包)
17:28:26 SYS@ prod >declare
17:29:34   2
17:29:34   3    my_task_name VARCHAR2(30);
17:29:34   4
17:29:34   5    my_sqltext CLOB;
17:29:34   6
17:29:34   7    begin
17:29:34   8
17:29:34   9       my_sqltext := 'select /*+ no_index(test test_ind) */ * from test where n=100';
17:29:34  10
17:29:34  11       my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
17:29:34  12
17:29:34  13       sql_text => my_sqltext,
17:29:34  14
17:29:34  15       user_name => 'SCOTT',
17:29:34  16
17:29:34  17       scope => 'COMPREHENSIVE',
17:29:34  18
17:29:34  19       time_limit => 60,
17:29:34  20
17:29:34  21       task_name => 'my_tun1',
17:29:34  22
17:29:34  23       description => 'Task to tune a query on a specified table');
17:29:34  24
17:29:34  25  end;
17:29:35  26  /
PL/SQL procedure successfully completed.

建立調優任務:
17:29:37 SYS@ prod >begin
17:30:39   2
17:30:39   3  DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'my_tun1');
17:30:39   4
17:30:39   5  end;
17:30:39   6
17:30:39   7  /
PL/SQL procedure successfully completed.

查看調優task:
17:32:47 SYS@ prod >set long 1000
17:33:17 SYS@ prod >set longchunksize 1000
17:33:24 SYS@ prod >set linesize 100
17:33:32 SYS@ prod >SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('my_tun1') from dual
DBMS_SQLTUNE.REPORT_TUNING_TASK('MY_TUN1')
----------------------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : my_tun1
Tuning Task Owner  : SYS
Workload Type      : Single SQL Statement
Scope              : COMPREHENSIVE
Time Limit(seconds): 60
Completion Status  : COMPLETED
Started at         : 11/07/2014 17:30:41
Completed at       : 11/07/2014 17:30:49
-------------------------------------------------------------------------------
Schema Name: SCOTT
SQL ID     : b1wdr0b0qzsbg
SQL Text   : select /*+ no_index(test test_ind) */ * from test where n=100
-------------------------------------------------------------------------------
DBMS_SQLTUNE.REPORT_TUNING_TASK('MY_TUN1')
----------------------------------------------------------------------------------------------------
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: 99.41%)
  
17:34:58 SYS@ prod >execute dbms_sqltune.accept_sql_profile(task_name =>'my_tun1',task_owner => 'SYS', replace => TRUE);
PL/SQL procedure successfully completed.

建立sql profile:
17:39:22 SYS@ prod >DECLARE
17:41:13   2
17:41:13   3  my_sqlprofile_name VARCHAR2(30);
17:41:13   4
17:41:13   5  begin
17:41:13   6
17:41:13   7  my_sqlprofile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (
17:41:13   8
17:41:13   9  task_name => 'my_tun1',
17:41:13  10
17:41:13  11  name => 'my_sqlprofile',force_match=>false);
17:41:13  12
17:41:13  13  end;
17:41:15  14  /
DECLARE
*
ERROR at line 1:
ORA-13830: SQL profile with category DEFAULT already exists for this SQL statement
ORA-06512: at "SYS.DBMS_SQLTUNE_INTERNAL", line 16259
ORA-06512: at "SYS.PRVT_SQLPROF_INFRA", line 31
ORA-06512: at "SYS.DBMS_SQLTUNE", line 7133
ORA-06512: at line 7

17:44:28 SYS@ prod >DECLARE
17:46:00   2
17:46:00   3  my_sqlprofile_name VARCHAR2(30);
17:46:00   4
17:46:00   5  begin
17:46:00   6
17:46:00   7  my_sqlprofile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (
17:46:00   8
17:46:00   9  task_name => 'my_tun1',
17:46:00  10
17:46:00  11  name => 'my_sqlprofile',force_match=>false,CATEGORY=>'scott');
17:46:00  12
17:46:00  13  end;
17:46:01  14  /
PL/SQL procedure successfully completed.

17:53:49 SYS@ prod >select name, CATEGORY,sql_text,status from dba_sql_profiles;
NAME                           CATEGORY
------------------------------ ------------------------------
SQL_TEXT
----------------------------------------------------------------------------------------------------
STATUS
--------
SYS_SQLPROF_0149899c759a0000   DEFAULT
select /*+ no_index(test test_ind) */ * from test where n=100
ENABLED
my_sqlprofile                  SCOTT
select /*+ no_index(test test_ind) */ * from test where n=100
ENABLED

刪除存在的sql profile:
17:53:51 SYS@ prod >exec DBMS_SQLTUNE.DROP_SQL_PROFILE(name =>'SYS_SQLPROF_0149899c759a0000');
PL/SQL procedure successfully completed.

17:55:20 SYS@ prod >exec DBMS_SQLTUNE.DROP_SQL_PROFILE(name =>'my_sqlprofile');
PL/SQL procedure successfully completed.

重新建立sql profile:
17:55:35 SYS@ prod >DECLARE
17:56:13   2
17:56:13   3  my_sqlprofile_name VARCHAR2(30);
17:56:13   4
17:56:13   5  begin
17:56:13   6
17:56:13   7  my_sqlprofile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (
17:56:13   8
17:56:13   9  task_name => 'my_tun1',
17:56:13  10
17:56:13  11  name => 'my_sqlprofile');
17:56:13  12
17:56:13  13  end;
17:56:16  14  /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.04

查看sql profile:
18:01:48 SYS@ prod >col name for a20
18:01:55 SYS@ prod >r
  1* select name,CATEGORY,SQL_TEXT,TASK_EXEC_NAME ,STATUS from dba_sql_profiles
NAME                 CATEGORY   SQL_TEXT
-------------------- ---------- --------------------------------------------------
TASK_EXEC_NAME                 STATUS
------------------------------ --------
my_sqlprofile        DEFAULT    select /*+ no_index(test test_ind) */ * from test
                                where n=100
EXEC_427                       ENABLED

3、以scott用戶的身份進行驗證
18:01:55 SYS@ prod >conn scott/tiger
Connected.
18:02:43 SCOTT@ prod >set autotrace on
18:02:46 SCOTT@ prod > select /*+ no_index(test test_ind) */ * from test where n=100;
         N
----------
       100
Elapsed: 00:00:00.05
Execution Plan
----------------------------------------------------------
Plan hash value: 3357096749
-----------------------------------------------------------------------------
| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |          |     1 |     5 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| TEST_IND |     1 |     5 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("N"=100)
Note
-----
   - SQL profile "my_sqlprofile" used for this statement
Statistics
----------------------------------------------------------
        790  recursive calls
          0  db block gets
        168  consistent gets
          6  physical reads
        116  redo size
        415  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         13  sorts (memory)
          0  sorts (disk)
          1  rows processed

可以看出即使使用了‘no_index'的hint,sql執行計劃仍使用index 訪問。  使用了  SQL profile "my_sql_profile" used for this statement  

由這個例子我們可以發現,在必要情況下,SQL Profile可以讓hint失效!


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女