sql tuning advisor(STA) 建議 建立sql profile

huyi_tony發表於2014-06-03
    sql tuning advisor(STA),是Oracle 10g起 提供的SQL自動最佳化建議工具。sql profile是用來穩定穩定(或者說固化)sql的執行計劃的工具。它是對outline功能的增強。
今天帶來一個 STA 推薦使用 sql profile 來最佳化sql的例子。

 環境準備:
 建立測試表

點選(此處)摺疊或開啟

  1. scott@ORCL>create table t1 as select * from dba_objects;

  2. Table created.

  3. scott@ORCL>create table t2 as select * from dba_objects;

  4. Table created.

  5. scott@ORCL>create index ind_t2 on t2(object_id);

  6. Index created.
蒐集統計資訊

點選(此處)摺疊或開啟

  1. scott@ORCL> exec dbms_stats.gather_table_stats(user,\'t1\',cascade=>true,method_opt=>\'for all indexed columns size auto\');

  2. PL/SQL procedure successfully completed.

  3. scott@ORCL>exec dbms_stats.gather_table_stats(user,\'t2\',cascade=>true,method_opt=>\'for all indexed columns size auto\');

  4. PL/SQL procedure successfully completed.
執行SQL,最佳化器選擇了 Hash join。估計的成本 是611, 邏輯讀是2192。

點選(此處)摺疊或開啟

  1. scott@ORCL>set autotrace traceonly
  2. scott@ORCL>select t1.*,t2.owner from t1,t2 where t1.object_name like \'%T1%\' and t1.object_id=t2.object_id;

  3. 51 rows selected.


  4. Execution Plan
  5. ----------------------------------------------------------
  6. Plan hash value: 1838229974

  7. ---------------------------------------------------------------------------
  8. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  9. ---------------------------------------------------------------------------
  10. | 0 | SELECT STATEMENT | | 3824 | 407K| 611 (1)| 00:00:08 |
  11. |* 1 | HASH JOIN | | 3824 | 407K| 611 (1)| 00:00:08 |
  12. |* 2 | TABLE ACCESS FULL| T1 | 3824 | 365K| 305 (1)| 00:00:04 |
  13. | 3 | TABLE ACCESS FULL| T2 | 76489 | 821K| 305 (1)| 00:00:04 |
  14. ---------------------------------------------------------------------------

  15. Predicate Information (identified by operation id):
  16. ---------------------------------------------------

  17.    1 - access(\"T1\".\"OBJECT_ID\"=\"T2\".\"OBJECT_ID\")
  18.    2 - filter(\"T1\".\"OBJECT_NAME\" LIKE \'%T1%\' AND \"T1\".\"OBJECT_NAME\" IS
  19.               NOT NULL)


  20. Statistics
  21. ----------------------------------------------------------
  22.           1 recursive calls
  23.           0 db block gets
  24.        2192 consistent gets
  25.           0 physical reads
  26.           0 redo size
  27.        5305 bytes sent via SQL*Net to client
  28.         556 bytes received via SQL*Net from client
  29.           5 SQL*Net roundtrips to/from client
  30.           0 sorts (memory)
  31.           0 sorts (disk)
  32.          51 rows processed
用HINT 強制做 Nested Loop方式。成本估算為7956 (大於Hash Join 的611,難怪沒走 NL方式)。但是實際上,邏輯讀1187(比 HJ的 2192 的少)。說明,最佳化器估算錯誤。這裡是因為,t1.object_name like '%T1%',Oracle對like的估算是 按照表行數的 5%。這裡過高的估計了,t1表返回的記錄數,也就過高估計巢狀的次數。

點選(此處)摺疊或開啟

  1. scott@ORCL>select /*+ use_nl(t1 t2) index(t2) */ t1.*,t2.owner
  2.   2 from t1,t2
  3.   3 where t1.object_name like \'%T1%\'
  4.   4 and t1.object_id=t2.object_id;

  5. 51 rows selected.


  6. Execution Plan
  7. ----------------------------------------------------------
  8. Plan hash value: 1386590592

  9. ---------------------------------------------------------------------------------------
  10. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  11. ---------------------------------------------------------------------------------------
  12. | 0 | SELECT STATEMENT | | 3824 | 407K| 7956 (1)| 00:01:36 |
  13. | 1 | NESTED LOOPS | | | | | |
  14. | 2 | NESTED LOOPS | | 3824 | 407K| 7956 (1)| 00:01:36 |
  15. |* 3 | TABLE ACCESS FULL | T1 | 3824 | 365K| 305 (1)| 00:00:04 |
  16. |* 4 | INDEX RANGE SCAN | IND_T2 | 1 | | 1 (0)| 00:00:01 |
  17. | 5 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
  18. ---------------------------------------------------------------------------------------

  19. Predicate Information (identified by operation id):
  20. ---------------------------------------------------

  21.    3 - filter(\"T1\".\"OBJECT_NAME\" LIKE \'%T1%\' AND \"T1\".\"OBJECT_NAME\" IS NOT
  22.               NULL)
  23.    4 - access(\"T1\".\"OBJECT_ID\"=\"T2\".\"OBJECT_ID\")


  24. Statistics
  25. ----------------------------------------------------------
  26.           1 recursive calls
  27.           0 db block gets
  28.        1187 consistent gets
  29.           0 physical reads
  30.           0 redo size
  31.        5305 bytes sent via SQL*Net to client
  32.         556 bytes received via SQL*Net from client
  33.           5 SQL*Net roundtrips to/from client
  34.           0 sorts (memory)
  35.           0 sorts (disk)
  36.          51 rows processed
處理方法,用sql tuning advisor(STA)來搞定它。

用sys使用者來查一下 帶最佳化sql的 id

點選(此處)摺疊或開啟

  1. sys@ORCL>select sql_id, sql_text from v$sql where sql_text like \'select t1.*,t2.owner%\';

  2. SQL_ID
  3. -------------
  4. SQL_TEXT
  5. -----------------------------------------------------------------------------------------------
  6. 4zbqykx89yc8v
  7. select t1.*,t2.owner from t1,t2 where t1.object_name like \'%T1%\' and t1.object_id=t2.object_id

sys使用者呼叫STA

點選(此處)摺疊或開啟

  1. var tuning_task varchar2(100);              -- 建立最佳化任務時,返回的任務名 用繫結變數儲存
  2.  
  3. BEGIN
  4.     :tuning_task := dbms_sqltune.create_tuning_task(sql_id => \'4zbqykx89yc8v\');   -- 建立最佳化任務,輸入待最佳化sql的id
  5.     dbms_sqltune.execute_tuning_task(:tuning_task);                                 -- 執行最佳化任務
  6.     dbms_output.put_line(:tuning_task);
  7. END;
  8. /

檢視最佳化成果

點選(此處)摺疊或開啟

  1. sys@ORCL>SELECT dbms_sqltune.report_tuning_task(:tuning_task) FROM dual;

  2. DBMS_SQLTUNE.REPORT_TUNING_TASK(:TUNING_TASK)
  3. --------------------------------------------------------------------------------
  4. GENERAL INFORMATION SECTION
  5. -------------------------------------------------------------------------------
  6. Tuning Task Name : TASK_567
  7. Tuning Task Owner : SYS
  8. Workload Type : Single SQL Statement
  9. Scope : COMPREHENSIVE
  10. Time Limit(seconds): 1800
  11. Completion Status : COMPLETED
  12. Started at : 06/03/2014 02:43:02
  13. Completed at : 06/03/2014 02:43:06

  14. -------------------------------------------------------------------------------
  15. Schema Name: SCOTT
  16. SQL ID : 4zbqykx89yc8v
  17. SQL Text : select t1.*,t2.owner from t1,t2 where t1.object_name like \'%T1%\'
  18.              and t1.object_id=t2.object_id

  19. -------------------------------------------------------------------------------
  20. FINDINGS SECTION (1 finding)
  21. -------------------------------------------------------------------------------

  22. 1- SQL Profile Finding (see explain plans section below)
  23. --------------------------------------------------------
  24.   A potentially better execution plan was found for this statement.

  25.   Recommendation (estimated benefit: 46.23%)                                    -- STA給出的建議 建立 sql profile
  26.   ------------------------------------------
  27.   - Consider accepting the recommended SQL profile.
  28.     execute dbms_sqltune.accept_sql_profile(task_name => \'TASK_567\',
  29.             task_owner => \'SYS\', replace => TRUE);

  30.   Validation results
  31.   ------------------
  32.   The SQL profile was tested by executing both its plan and the original plan
  33.   and measuring their respective execution statistics. A plan may have been
  34.   only partially executed if the other could be run to completion in less time.

  35.                            Original Plan With SQL Profile % Improved
  36.                            ------------- ---------------- ----------
  37.   Completion Status: COMPLETE COMPLETE
  38.   Elapsed Time (s): .069781 .061671 11.62 %
  39.   CPU Time (s): .069689 .06179 11.33 %
  40.   User I/O Time (s): 0 0
  41.   Buffer Gets: 2188 1174 46.34 %
  42.   Physical Read Requests: 0 0
  43.   Physical Write Requests: 0 0
  44.   Physical Read Bytes: 0 0
  45.   Physical Write Bytes: 0 0
  46.   Rows Processed: 51 51
  47.   Fetches: 51 51
  48.   Executions: 1 1

  49.   Notes
  50.   -----
  51.   1. Statistics for the original plan were averaged over 10 executions.
  52.   2. Statistics for the SQL profile plan were averaged over 10 executions.

  53. -------------------------------------------------------------------------------
  54. EXPLAIN PLANS SECTION
  55. -------------------------------------------------------------------------------

  56. 1- Original With Adjusted Cost
  57. ------------------------------
  58. Plan hash value: 1838229974

  59. ---------------------------------------------------------------------------
  60. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  61. ---------------------------------------------------------------------------
  62. | 0 | SELECT STATEMENT | | 56 | 6104 | 611 (1)| 00:00:08 |
  63. |* 1 | HASH JOIN | | 56 | 6104 | 611 (1)| 00:00:08 |
  64. |* 2 | TABLE ACCESS FULL| T1 | 56 | 5488 | 305 (1)| 00:00:04 |
  65. | 3 | TABLE ACCESS FULL| T2 | 76489 | 821K| 305 (1)| 00:00:04 |
  66. ---------------------------------------------------------------------------

  67. Predicate Information (identified by operation id):
  68. ---------------------------------------------------

  69.    1 - access(\"T1\".\"OBJECT_ID\"=\"T2\".\"OBJECT_ID\")
  70.    2 - filter(\"T1\".\"OBJECT_NAME\" LIKE \'%T1%\' AND \"T1\".\"OBJECT_NAME\" IS
  71.               NOT NULL)

  72. 2- Using SQL Profile                                                                -- sql profile 固化的執行計劃 走NL
  73. --------------------
  74. Plan hash value: 1386590592

  75. --------------------------------------------------------------------------------
  76. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Tim
  77. e |
  78. --------------------------------------------------------------------------------
  79. | 0 | SELECT STATEMENT | | 56 | 6104 | 417 (1)| 00:
  80. 00:06 |
  81. | 1 | NESTED LOOPS | | | | |
  82.       |
  83. | 2 | NESTED LOOPS | | 56 | 6104 | 417 (1)| 00:
  84. 00:06 |

  85. DBMS_SQLTUNE.REPORT_TUNING_TASK(:TUNING_TASK)
  86. --------------------------------------------------------------------------------
  87. |* 3 | TABLE ACCESS FULL | T1 | 56 | 5488 | 305 (1)| 00:
  88. 00:04 |
  89. |* 4 | INDEX RANGE SCAN | IND_T2 | 1 | | 1 (0)| 00:
  90. 00:01 |
  91. | 5 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:
  92. 00:01 |
  93. --------------------------------------------------------------------------------

  94. Predicate Information (identified by operation id):
  95. ---------------------------------------------------

  96.    3 - filter(\"T1\".\"OBJECT_NAME\" LIKE \'%T1%\' AND \"T1\".\"OBJECT_NAME\" IS NOT
  97.               NULL)
  98.    4 - access(\"T1\".\"OBJECT_ID\"=\"T2\".\"OBJECT_ID\")

安裝STA建議,來建立sql profile

點選(此處)摺疊或開啟

  1. sys@ORCL>execute dbms_sqltune.accept_sql_profile(task_name => \'TASK_567\', task_owner => \'SYS\', replace => TRUE);

  2. PL/SQL procedure successfully completed.

檢查測試結果。安裝sql profile固化的執行計劃來執行。而且,現在的成本估算比較客觀(417, 低於 Hash join的 611)


點選(此處)摺疊或開啟

  1. scott@ORCL>set autotrace traceonly
  2. scott@ORCL>select t1.*,t2.owner from t1,t2 where t1.object_name like \'%T1%\' and t1.object_id=t2.object_id;

  3. 51 rows selected.


  4. Execution Plan
  5. ----------------------------------------------------------
  6. Plan hash value: 1386590592

  7. ---------------------------------------------------------------------------------------
  8. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  9. ---------------------------------------------------------------------------------------
  10. | 0 | SELECT STATEMENT | | 56 | 6104 | 417 (1)| 00:00:06 |
  11. | 1 | NESTED LOOPS | | | | | |
  12. | 2 | NESTED LOOPS | | 56 | 6104 | 417 (1)| 00:00:06 |
  13. |* 3 | TABLE ACCESS FULL | T1 | 56 | 5488 | 305 (1)| 00:00:04 |
  14. |* 4 | INDEX RANGE SCAN | IND_T2 | 1 | | 1 (0)| 00:00:01 |
  15. | 5 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
  16. ---------------------------------------------------------------------------------------

  17. Predicate Information (identified by operation id):
  18. ---------------------------------------------------

  19.    3 - filter(\"T1\".\"OBJECT_NAME\" LIKE \'%T1%\' AND \"T1\".\"OBJECT_NAME\" IS NOT
  20.               NULL)
  21.    4 - access(\"T1\".\"OBJECT_ID\"=\"T2\".\"OBJECT_ID\")

  22. Note
  23. -----
  24.    - SQL profile \"SYS_SQLPROF_01466078fe610000\" used for this statement                  -- SQL profile 生效了,按照固化的執行計劃走


  25. Statistics
  26. ----------------------------------------------------------
  27.          35 recursive calls
  28.           0 db block gets
  29.        1198 consistent gets
  30.           1 physical reads
  31.           0 redo size
  32.        5305 bytes sent via SQL*Net to client
  33.         556 bytes received via SQL*Net from client
  34.           5 SQL*Net roundtrips to/from client
  35.           1 sorts (memory)
  36.           0 sorts (disk)
  37.          51 rows processed

新的問題: 如果,替換like後面的字串,sql profile就失效了。換成 t1.object_name like '%T2%'後,有走Hash join了


點選(此處)摺疊或開啟

  1. scott@ORCL>select t1.*,t2.owner from t1,t2 where t1.object_name like \'%T2%\' and t1.object_id=t2.object_id;

  2. 124 rows selected.


  3. Execution Plan
  4. ----------------------------------------------------------
  5. Plan hash value: 1838229974

  6. ---------------------------------------------------------------------------
  7. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  8. ---------------------------------------------------------------------------
  9. | 0 | SELECT STATEMENT | | 3824 | 407K| 611 (1)| 00:00:08 |
  10. |* 1 | HASH JOIN | | 3824 | 407K| 611 (1)| 00:00:08 |
  11. |* 2 | TABLE ACCESS FULL| T1 | 3824 | 365K| 305 (1)| 00:00:04 |
  12. | 3 | TABLE ACCESS FULL| T2 | 76489 | 821K| 305 (1)| 00:00:04 |
  13. ---------------------------------------------------------------------------

  14. Predicate Information (identified by operation id):
  15. ---------------------------------------------------

  16.    1 - access(\"T1\".\"OBJECT_ID\"=\"T2\".\"OBJECT_ID\")
  17.    2 - filter(\"T1\".\"OBJECT_NAME\" LIKE \'%T2%\' AND \"T1\".\"OBJECT_NAME\" IS
  18.               NOT NULL)


  19. Statistics
  20. ----------------------------------------------------------
  21.           1 recursive calls
  22.           0 db block gets
  23.        2197 consistent gets
  24.           0 physical reads
  25.           0 redo size
  26.        9356 bytes sent via SQL*Net to client
  27.         611 bytes received via SQL*Net from client
  28.          10 SQL*Net roundtrips to/from client
  29.           0 sorts (memory)
  30.           0 sorts (disk)
  31.         124 rows processed

新問題的處理的方法。sys使用者重新建立sql profile,force_match=>true強制匹配

點選(此處)摺疊或開啟

  1. sys@ORCL>execute dbms_sqltune.accept_sql_profile(task_name =>\'TASK_567\', task_owner=>\'SYS\', replace=>TRUE,force_match=>true);

  2. PL/SQL procedure successfully completed.

處理過後

點選(此處)摺疊或開啟

  1. scott@ORCL>select t1.*,t2.owner from t1,t2 where t1.object_name like \'%T2%\' and t1.object_id=t2.object_id;

  2. 124 rows selected.


  3. Execution Plan
  4. ----------------------------------------------------------
  5. Plan hash value: 1386590592

  6. ---------------------------------------------------------------------------------------
  7. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  8. ---------------------------------------------------------------------------------------
  9. | 0 | SELECT STATEMENT | | 56 | 6104 | 417 (1)| 00:00:06 |
  10. | 1 | NESTED LOOPS | | | | | |
  11. | 2 | NESTED LOOPS | | 56 | 6104 | 417 (1)| 00:00:06 |
  12. |* 3 | TABLE ACCESS FULL | T1 | 56 | 5488 | 305 (1)| 00:00:04 |
  13. |* 4 | INDEX RANGE SCAN | IND_T2 | 1 | | 1 (0)| 00:00:01 |
  14. | 5 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
  15. ---------------------------------------------------------------------------------------

  16. Predicate Information (identified by operation id):
  17. ---------------------------------------------------

  18.    3 - filter(\"T1\".\"OBJECT_NAME\" LIKE \'%T2%\' AND \"T1\".\"OBJECT_NAME\" IS NOT
  19.               NULL)
  20.    4 - access(\"T1\".\"OBJECT_ID\"=\"T2\".\"OBJECT_ID\")

  21. Note
  22. -----
  23.    - SQL profile \"SYS_SQLPROF_0146607cb3e40001\" used for this statement                     -- 這裡 SQL profile又生效了


  24. Statistics
  25. ----------------------------------------------------------
  26.           6 recursive calls
  27.           0 db block gets
  28.        1253 consistent gets
  29.           1 physical reads
  30.           0 redo size
  31.        9356 bytes sent via SQL*Net to client
  32.         611 bytes received via SQL*Net from client
  33.          10 SQL*Net roundtrips to/from client
  34.           0 sorts (memory)
  35.           0 sorts (disk)
  36.         124 rows processed




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12238525/viewspace-1174894/,如需轉載,請註明出處,否則將追究法律責任。

相關文章