2014-10-02 Created By BaoXinjian
一、摘要
SQL优化是有一定难度的工作,需要DBA具有扎实的知识和较丰富的经验。
在ORACLE10g以后,引入了一些自动调优技术,包括sql tuning advisor、sql access advisor、ADDM等,不需要了解JOIN的类型、次序,也不需了解优化器,新手也能用这些工具进行一些优化工作。
二、SQL Tunning Advisor
SQL Tuning Advisor可以在Enterprise Manager图形界面中调用,也可通过过程包调用。
1. 以下内容可以作为sql tuning advisor的输入,调优其中的问题sql:
2. 调用sql tuning advisor时,优化器进入调优模式。
Oracle优化器有两种模式:
(1). Normal mode
快速产生对大多数sql来说合理的计划。要求生成计划的时间非常短。
(2).Tuning mode
进行额外分析,如sql结构分析、sql profile、访问路径分析、替代写法等等,给出优化建议。通常调优一句sql需要几分钟,下面减少其中的sql profile。
三、SQL Profile
SQL Profile不是执行计划,而是提供以下信息帮助优化器选择plan
1. 环境:db配置,绑定变量值,optimizer statistics,data set
2. Supplemental Statistics
因此可以说sql profile之于sql,相当于optimizer statistics之于table/index。
3. SQL Profile的优点是:
4. Sql profile用来优化sql。当然使用了sql profile之后,也会达到稳定执行计划的目的。
四、案例
案例:通过SQL Tunning Advisor查找SQL现有的效率和推荐的最优化SQL Plan
Step1. 准备权限
CONNECT / AS SYSDBA GRANT ADVISOR TO SYSTEM; GRANT SELECT_CATALOG_ROLE TO SYSTEM; GRANT EXECUTE ON DBMS_SQLTUNE TO SYSTEM;
Step2. Create Task创建诊断任务
DECLARE bxj_task_name VARCHAR2 (30); bxj_sqltext CLOB; BEGIN bxj_sqltext :=
'SELECT * '
|| 'FROM sh.sales '
|| 'WHERE prod_id = 10 AND '
|| 'cust_id = 100 '; DBMS_OUTPUT.PUT_LINE (bxj_sqltext); bxj_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK ( sql_text => bxj_sqltext, user_name => 'SYSTEM', scope => 'COMPREHENSIVE', time_limit => 60, task_name => 'BXJ_SQL_TUNING_TASK', description => 'Task To Tune A Query On A Specified PRODUCT' ); END;
Step3. Query Task查询诊断任务状态
SELECT task_name FROM dba_advisor_log WHERE task_name = 'BXJ_SQL_TUNING_TASK';
Step4. Execute Task执行诊断任务
BEGIN DBMS_SQLTUNE.EXECUTE_TUNING_TASK (task_name => 'BXJ_SQL_TUNING_TASK'); END;
Step5. Query Task查询诊断任务状态
SELECT task_id, task_name, status FROM dba_advisor_log WHERE task_name = 'BXJ_SQL_TUNING_TASK';
Step6. Task Result查看诊断人任务结果
SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK ('BXJ_SQL_TUNING_TASK') FROM DUAL;
GENERAL INFORMATION SECTION -------------------------------------------------------------------------------
Tuning Task Name : BXJ_SQL_TUNING_TASK Tuning Task Owner : SYSTEM Workload Type : Single SQL Statement Scope : COMPREHENSIVE Time Limit(seconds): 60 Completion Status : COMPLETED Started at : 10/02/2014 04:08:26 Completed at : 10/02/2014 04:08:27
-------------------------------------------------------------------------------
Schema Name: SYSTEM SQL ID : 276wx1tuaxwpg SQL Text : SELECT * FROM sh.sales WHERE prod_id = 10 AND cust_id = 100
-------------------------------------------------------------------------------
FINDINGS SECTION (2 findings) -------------------------------------------------------------------------------
1- SQL Profile Finding (see explain plans section below) --------------------------------------------------------
A potentially better execution plan was found for this statement. Recommendation (estimated benefit: 25.02%) ------------------------------------------
- Consider accepting the recommended SQL profile. execute dbms_sqltune.accept_sql_profile(task_name =>
'BXJ_SQL_TUNING_TASK', task_owner => 'SYSTEM', replace => TRUE); Validation results ------------------
The SQL profile was tested by executing both its plan and the original plan
and measuring their respective execution statistics. A plan may have been only partially executed if the other could be run to completion in less time. Original Plan With SQL Profile % Improved ------------- ---------------- ----------
Completion Status: COMPLETE COMPLETE Elapsed Time(us): 211 70 66.82 % CPU Time(us): 299 100 66.55 %
User I/O Time(us): 0 0 Buffer Gets: 52 39 25 % Physical Read Requests: 0 0 Physical Write Requests: 0 0 Physical Read Bytes: 0 0 Physical Write Bytes: 0 0 Rows Processed: 0 0 Fetches: 0 0 Executions: 1 1 Notes -----
1. The original plan was first executed to warm the buffer cache. 2. Statistics for original plan were averaged over next 9 executions. 3. The SQL profile plan was first executed to warm the buffer cache. 4. Statistics for the SQL profile plan were averaged over next 9 executions. 2- 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: 86.25%) ------------------------------------------
- Consider running the Access Advisor to improve the physical schema design or creating the recommended index. If you choose to create the recommended index, consider dropping the index "SH"."SALES_CUST_BIX" because it is a prefix of the recommended index. create index SH.IDX$$_00270001 on SH.SALES("CUST_ID","PROD_ID"); 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 With Adjusted Cost ------------------------------
Plan hash value: 811666046
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 29 | 58 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ALL | | 1 | 29 | 58 (0)| 00:00:01 | 1 | 28 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES | 1 | 29 | 58 (0)| 00:00:01 | 1 | 28 |
| 3 | BITMAP CONVERSION TO ROWIDS | | | | | | | |
| 4 | BITMAP AND | | | | | | | |
|* 5 | BITMAP INDEX SINGLE VALUE | SALES_CUST_BIX | | | | | 1 | 28 |
|* 6 | BITMAP INDEX SINGLE VALUE | SALES_PROD_BIX | | | | | 1 | 28 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
5 - access("CUST_ID"=100) 6 - access("PROD_ID"=10) 2- Using SQL Profile --------------------
Plan hash value: 511273406
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 29 | 29 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ALL | | 1 | 29 | 29 (0)| 00:00:01 | 1 | 28 |
|* 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES | 1 | 29 | 29 (0)| 00:00:01 | 1 | 28 |
| 3 | BITMAP CONVERSION TO ROWIDS | | | | | | | |
|* 4 | BITMAP INDEX SINGLE VALUE | SALES_PROD_BIX | | | | | 1 | 28 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
2 - filter("CUST_ID"=100) 4 - access("PROD_ID"=10) 3- Using New Indices --------------------
Plan hash value: 2089281862
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 29 | 4 (0)| 00:00:01 | | |
| 1 | TABLE ACCESS BY GLOBAL INDEX ROWID| SALES | 1 | 29 | 4 (0)| 00:00:01 | ROWID | ROWID |
|* 2 | INDEX RANGE SCAN | IDX$$_00270001 | 1 | | 3 (0)| 00:00:01 | | |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id): ---------------------------------------------------
2 - access("CUST_ID"=100 AND "PROD_ID"=10) -------------------------------------------------------------------------------
Step7. Task Accept接受诊断任务结果
DECLARE bxj_sqlprofile_name VARCHAR2 (30); BEGIN bxj_sqlprofile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (task_name => 'BXJ_SQL_TUNING_TASK', name => 'BXJ_SQL_PROFILE'); DBMS_OUTPUT.PUT_LINE ('bxj_sqlprofile_name=' || bxj_sqlprofile_name); END;
Step8. Task Remove移除诊断任务
BEGIN DBMS_SQLTUNE.DROP_TUNING_TASK ('BXJ_SQL_TUNING_TASK'); END;
Step9. 其他信息
注意:无法使用SQL中Hints,导致Hints无法使用
SELECT * FROM DBA_SQLTUNE_STATISTICS; SELECT * FROM DBA_SQLTUNE_BINDS; SELECT * FROM DBA_SQLTUNE_PLANS;
Thanks and Regards
参考:metalink资料 Using the DBMS_SQLTUNE package to Run the Sql Tuning Advisor (Doc ID 262687.1)
参考:luw http://blog.itpub.net/18474/abstract/1/