SQL Profile就是为某一SQL语句提供除了系统统计信息、对象(表和索引等)统计信息之外的其他信息,比如运行环境、额外的更准确的统计信息,以帮助优化器为SQL语句选择更适合的执行计划。
SQL Profiles可以说是Outlines的进化。Outlines能够实现的功能SQL Profiles也完全能够实现,而SQL Profiles具有Outlines不具备的优化,最重要的有二点:
    SQL Profiles更容易生成、更改和控制。
    SQL Profiles在对SQL语句的支持上做得更好,也就是适用范围更广。
使用SQL Profiles两个目的:
    锁定或者说是稳定执行计划。
    在不能修改应用中的SQL的情况下使SQL语句按指定的执行计划运行。
参考老熊的博客,链接:http://www.laoxiong.net/sql-profiles-partii.html    http://www.laoxiong.net/sql-profiles-part.html   http://blog.sina.com.cn/s/blog_5037eacb01011mgu.htm

1.实验环境构造语句:

create table bys.t1 as select * from dba_objects;

 create index bys.t1_idx on t1(object_id);

 exec dbms_stats.gather_table_stats('bys','t1',cascade=>true,degree=>4);

 set autotrace trace;

 select a.*,b.owner from t1 a,t1 b where a.object_name like '%T1%' and a.object_id=b.object_id;

 select /*+ use_nl(a b) index(t2) */ a.*,b.owner from t1 a,t1 b where a.object_name like '%T1%' and a.object_id=b.object_id;

 set autotrace off;

 explain plan for select /*+ use_nl(a b) index(t2) */ a.*,b.owner from t1 a,t1 b where a.object_name like '%T1%' and a.object_id=b.object_id;

 col sql_text for a100

 SELECT SQL_ID,SQL_TEXT FROM V$SQL WHERE SQL_TEXT LIKE '%a.*,b.owner from t1 a,t1 b%';

 ####2t5xqt4d1dsaw

10g开始,v$sql_plan中就包括了SQL语句OUTLINE数据,也就是稳定执行计划的Hints。如下:

 set pagesize 1000

 SQL> select * from table(dbms_xplan.display_cursor('2t5xqt4d1dsaw',null,'outline'));

 PLAN_TABLE_OUTPUT

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

 SQL_ID  2t5xqt4d1dsaw, child number 0

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

 select /*+ use_nl(a b) index(t2) */ a.*,b.owner from t1 a,t1 b where

 a.object_name like '%T1%' and a.object_id=b.object_id

 Plan hash value: 190596302

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

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

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

 |   0 | SELECT STATEMENT            |        |       |       |   979 (100)|          |

 |   1 |  TABLE ACCESS BY INDEX ROWID| T1     |     1 |     9 |     2   (0)| 00:00:01 |

 |   2 |   NESTED LOOPS              |        |   471 | 43803 |   979   (1)| 00:00:12 |

 |*  3 |    TABLE ACCESS FULL        | T1     |   471 | 39564 |    36   (0)| 00:00:01 |

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

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


Outline Data              ----------这一部分:  */
 -------------
   /*+
       BEGIN_OUTLINE_DATA
       IGNORE_OPTIM_EMBEDDED_HINTS
       OPTIMIZER_FEATURES_ENABLE('10.2.0.1')
       ALL_ROWS
       OUTLINE_LEAF(@"SEL$1")
       FULL(@"SEL$1" "A"@"SEL$1")
       INDEX(@"SEL$1" "B"@"SEL$1" ("T1"."OBJECT_ID"))
       LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1")
       USE_NL(@"SEL$1" "B"@"SEL$1")
       END_OUTLINE_DATA
   */


 PLAN_TABLE_OUTPUT

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

 Predicate Information (identified by operation id):

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

    3 - filter("A"."OBJECT_NAME" LIKE '%T1%')

    4 - access("A"."OBJECT_ID"="B"."OBJECT_ID")

 ###############################################################################

2.开始创建并应用SQL Profile
 使用未加HINT的SQL语句,并指定SQL_PROFILE名字:SQLPROFILE_T1

注意事项:两个引号---如('10.2.0.1')要写成(''10.2.0.1'')--'%T1%'写成''%T1%''

 SQL语句结尾的;不要写上,绑定变量值是'1'时,要输入''1''

  declare

  v_hints sys.sqlprof_attr;

  begin

  v_hints:=sys.sqlprof_attr(

       'BEGIN_OUTLINE_DATA',

       'IGNORE_OPTIM_EMBEDDED_HINTS',

       'OPTIMIZER_FEATURES_ENABLE(''10.2.0.1'')',

       'ALL_ROWS',

       'OUTLINE_LEAF(@"SEL$1")',

       'FULL(@"SEL$1" "A"@"SEL$1")',

       'INDEX(@"SEL$1" "B"@"SEL$1" ("T1"."OBJECT_ID"))',

       'LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1")',

       'USE_NL(@"SEL$1" "B"@"SEL$1")',

       'END_OUTLINE_DATA');

 dbms_sqltune.import_sql_profile(

 'select a.*,b.owner from t1 a,t1 b where a.object_name like ''%T1%'' and a.object_id=b.object_id',

 v_hints,
'SQLPROFILE_T1',                

 force_match=>true,replace=>true);

 end;

 /

删除语句:
 exec dbms_sqltune.drop_sql_profile(name =>'SQLPROFILE_T1' );

 ######

3.验证SQL语句是否使用上一步创建的SQL_PROFILE:
 SQL> set autotrace trace;

 SQL> select a.*,b.owner from t1 a,t1 b where a.object_name like '%T1%' and a.object_id=b.object_id;

 23 rows selected.

 Execution Plan

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

 Plan hash value: 190596302

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

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

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

 |   0 | SELECT STATEMENT            |        |   471 | 43803 |   979   (1)| 00:00:12 |

 |   1 |  TABLE ACCESS BY INDEX ROWID| T1     |     1 |     9 |     2   (0)| 00:00:01 |

 |   2 |   NESTED LOOPS              |        |   471 | 43803 |   979   (1)| 00:00:12 |

 |*  3 |    TABLE ACCESS FULL        | T1     |   471 | 39564 |    36   (0)| 00:00:01 |

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

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

 Predicate Information (identified by operation id):

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

    3 - filter("A"."OBJECT_NAME" LIKE '%T1%')

    4 - access("A"."OBJECT_ID"="B"."OBJECT_ID")

 Note

 -----

    - SQL profile "SQLPROFILE_T1" used for this statement


 Statistics

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

           1  recursive calls

           0  db block gets

         163  consistent gets

           0  physical reads

           0  redo size

        2609  bytes sent via SQL*Net to client

         392  bytes received via SQL*Net from client

           3  SQL*Net roundtrips to/from client

           0  sorts (memory)

           0  sorts (disk)

          23  rows processed          0  sorts (disk)

 #####################################################################       

使用Oracle的SQL Tuning Advisor固定执行计划--SQL_ID
----通过sql_id的方式  sql_id => 'a2h6pzvqncfvg',--想调优的sql_id
 show serveroutput

 set serveroutput on;


 DECLARE  

     a_tuning_task VARCHAR2(30);  

   BEGIN  

     a_tuning_task := dbms_sqltune.create_tuning_task(sql_id => 'a2h6pzvqncfvg',task_name => 'tuning_test');    

     dbms_sqltune.execute_tuning_task(a_tuning_task);   

   END;  

   / 

 set long 1000

 SELECT dbms_sqltune.report_tuning_task('tuning_test') FROM dual; 

  

 这里的输出中的sql_id是从v$sql查出,对应的是没有加hint的SQL。

 如果SQL Tuning Advisor找到了理想的执行计划,下一步就是:
Accept SQL Profile,接受这个SQL Profile。

 ## execute dbms_sqltune.accept_sql_profile(task_name =>'tuning_test' ,replace => TRUE,force_match=>true);

 完成后验证语句:

 set autotrace trace;

 select a.*,b.owner from t1 a,t1 b where a.object_name like '%T1%' and a.object_id=b.object_id;

 set autotrace off;

删除SQL语句:
 exec dbms_sqltune.drop_tuning_task('tuning_test');  

  如果未找到理想的执行计划,则参考下一个方法。

 ##################################################################

使用Oracle的SQL Tuning Advisor固定执行计划--使用SQL_TEXT,参考以下:
 DECLARE

  my_task_name VARCHAR2 (30);

  my_sqltext CLOB;

  BEGIN

  my_sqltext := 'select * from test where OBJECT_ID=15';  --想调优的sql

  my_task_name := dbms_sqltune.create_tuning_task (sql_text=> my_sqltext,

  --bind_list =>  'UNDO$',

  --user_name => 'SONG',

  --scope => 'COMPREHENSIVE',

  --time_limit => 60,

  task_name => 'sql_tuning_test'

  --description => 'Tuning Task'

  );

  END;

  /

  

  exec dbms_sqltune.execute_tuning_task('sql_tuning_test');   --执行调优的任务

   SELECT STATUS FROM USER_ADVISOR_TASKS WHERE task_name = 'sql_tuning_test'; --查看调优作业的状态

  SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('sql_tuning_test') FROM DUAL;--查看调优的建议

  exec dbms_sqltune.drop_tuning_task('sql_tuning_test');--删除任务