0
点赞
收藏
分享

微信扫一扫

sql profiles和dbms_sqltune(sta)


1.先通过v$SQL查找SQL_ID 

var tuning_task varchar2(100);  
 DECLARE  
 l_sql_id v$session.sql_id%TYPE;  
 l_tuning_task VARCHAR2(30);  
 BEGIN  
 l_sql_id:='4zbqykx89yc8v';  --SQL_ID
 l_tuning_task := dbms_sqltune.create_tuning_task(sql_id => l_sql_id);  
 :tuning_task:=l_tuning_task;  
 dbms_sqltune.execute_tuning_task(l_tuning_task);  
 dbms_output.put_line(l_tuning_task);  
 END;  
 / 2.
SELECT dbms_sqltune.report_tuning_task(:tuning_task) FROM dual;  
SQL> SELECT dbms_sqltune.report_tuning_task('TASK_43') FROM dual;  

 DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_43')
 --------------------------------------------------------------------------------
 GENERAL INFORMATION SECTION
 -------------------------------------------------------------------------------
 Tuning Task Name                  : TASK_43
 Tuning Task Owner                 : AIKI
 Scope                             : COMPREHENSIVE
 Time Limit(seconds)               : 1800
 Completion Status                 : COMPLETED
 Started at                        : 09/28/2012 15:42:33
 Completed at                      : 09/28/2012 15:42:33
 Number of SQL Profile Findings    : 1


 DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_43')
 --------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Schema Name: AIKI
 SQL ID     : awxu67tt24sz0
 SQL Text   :  select t1.*,t2.owner from t1,t2 where t1.object_name like
              '%T1%' and t1.object_id=t2.object_id

 -------------------------------------------------------------------------------
 FINDINGS SECTION (1 finding)
 -------------------------------------------------------------------------------

 1- SQL Profile Finding (see explain plans section below)

 DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_43')
 --------------------------------------------------------------------------------
 --------------------------------------------------------
   A potentially better execution plan was found for this statement.

   Recommendation (estimated benefit: 50.46%)
   ------------------------------------------
   - Consider accepting the recommended SQL profile.
     execute dbms_sqltune.accept_sql_profile(task_name => 'TASK_43', replace
             => TRUE);

 -------------------------------------------------------------------------------
 EXPLAIN PLANS SECTION

 DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_43')
 --------------------------------------------------------------------------------
 -------------------------------------------------------------------------------

 1- Original With Adjusted Cost
 ------------------------------
 Plan hash value: 1838229974

 ---------------------------------------------------------------------------
 | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
 ---------------------------------------------------------------------------
 |   0 | SELECT STATEMENT   |      |    25 |   975 |   218   (3)| 00:00:03 |
 |*  1 |  HASH JOIN         |      |    25 |   975 |   218   (3)| 00:00:03 |

 DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_43')
 --------------------------------------------------------------------------------
 |*  2 |   TABLE ACCESS FULL| T1   |    25 |   700 |    58   (4)| 00:00:01 |
 |   3 |   TABLE ACCESS FULL| T2   | 50318 |   540K|   159   (2)| 00:00:02 |
 ---------------------------------------------------------------------------

 Predicate Information (identified by operation id):
 ---------------------------------------------------

    1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
    2 - filter("T1"."OBJECT_NAME" LIKE '%T1%')

 2- Using SQL Profile

 DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_43')
 --------------------------------------------------------------------------------
 --------------------
 Plan hash value: 3787413387

 --------------------------------------------------------------------------------
 ------
 | Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time
      |
 --------------------------------------------------------------------------------
 ------
 |   0 | SELECT STATEMENT            |        |    25 |   975 |   108   (2)| 00:0
 0:02 |

 DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_43')
 --------------------------------------------------------------------------------
 |   1 |  TABLE ACCESS BY INDEX ROWID| T2     |     1 |    11 |     2   (0)| 00:0
 0:01 |
 |   2 |   NESTED LOOPS              |        |    25 |   975 |   108   (2)| 00:0
 0:02 |
 |*  3 |    TABLE ACCESS FULL        | T1     |    25 |   700 |    58   (4)| 00:0
 0:01 |
 |*  4 |    INDEX RANGE SCAN         | T2_IDX |     1 |       |     1   (0)| 00:0
 0:01 |
 --------------------------------------------------------------------------------
 ------


 DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_43')
 --------------------------------------------------------------------------------
 Predicate Information (identified by operation id):
 ---------------------------------------------------

    3 - filter("T1"."OBJECT_NAME" LIKE '%T1%')
    4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")

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



 Execution Plan
 ----------------------------------------------------------
 Plan hash value: 1388734953

 -----------------------------------------------------------------
 | Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
 -----------------------------------------------------------------
 |   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
 |   1 |  FAST DUAL       |      |     1 |     2   (0)| 00:00:01 |
 -----------------------------------------------------------------


 Statistics
 ----------------------------------------------------------
         455  recursive calls
         362  db block gets
        1004  consistent gets
           0  physical reads
           0  redo size
       16543  bytes sent via SQL*Net to client
       10178  bytes received via SQL*Net from client
          49  SQL*Net roundtrips to/from client
          10  sorts (memory)
           0  sorts (disk)
           1  rows processed

3.根据提示固定执行

execute dbms_sqltune.accept_sql_profile(task_name => :tuning_task,replace => TRUE,force_match=>true);

4.常用的些视图和SQL

select name,category,signature,type,status,force_matching from dba_sql_profiles; 

select * from sys.sqlprof$attr; 

5.以上内容参考“老熊三分地”

Oracle 11g从发布到现在,也有几个年头了。而在国内来说,Oracle 10g仍然是主流,甚至一些电信运营商的核心系统仍然在使用9i。作为Oracle 10g的一项新特性,SQL Profiles被使用得并不太多。不管是在论坛、个人的BLOG还是其他一些地方,SQL Profiles的介绍也相对较少。对我个人来说,已经在多个优化场合中使用SQL Profiles,在这里向大家介绍SQL Profiles,就是希望能够了解Oracle数据库的这一功能。

SQL Profiles可以说是Outlines的进化。Outlines能够实现的功能SQL Profiles也完全能够实现,而SQL Profiles具有Outlines不具备的优化,个人认为最重要的有2点:

  • SQL Profiles更容易生成、更改和控制。
  • SQL Profiles在对SQL语句的支持上做得更好,也就是适用范围更广。

关于这2方面的优点,我后面会详细地阐述。

现在我在使用Outlines的场合,均使用SQL Profiles来替代。有一次准备对1条SQL语句使用Outline进行执行计划的稳定,结果使用Outline之后,系统出现大量的library cache latch的争用,不得不关闭Outline的使用,但是改用SQL Profiles不再有这个问题。这或许是个BUG,不过既然能用SQL Profiles代替,也就没再深入去研究这个问题。

使用SQL Profiles无非是两个目的:

  • 锁定或者说是稳定执行计划。
  • 在不能修改应用中的SQL的情况下使SQL语句按指定的执行计划运行。

那么SQL Profile到底是什么?在我看来,SQL Profile就是为某一SQL语句提供除了系统统计信息、对象(表和索引等)统计信息之外的其他信息,比如运行环境、额外的更准确的统计信息,以帮助优化器为SQL语句选择更适合的执行计划。这些说法显得比较枯燥,还是来看看下面的测试。

首先建2个测试表:


1. SQL> create table t1 as select object_id,object_name from dba_objects where
2.   
3. 表已创建。  
4.   
5. SQL> create table t2 as select * from
6.   
7. 表已创建。  
8.   
9. SQL> create index t2_idx on
10.   
11. 索引已创建。  
12.   
13. SQL> exec dbms_stats.gather_table_stats(user,'t1',cascade=>true,method_opt=>'for all columns size 1');  
14.   
15. PL/SQL 过程已成功完成。  
16.   
17. SQL> exec dbms_stats.gather_table_stats(user,'t2',cascade=>true,method_opt=>'for all columns size 1');  
18.   
19. PL/SQL 过程已成功完成。


然后看看下面这一条SQL:


1. SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and
2.   
3. 已选择29行。  
4.   
5. 执行计划  
6. ----------------------------------------------------------
7. Plan hash value: 1838229974  
8.   
9. ---------------------------------------------------------------------------
10. | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time
11. ---------------------------------------------------------------------------
12. |   0 | SELECT
13. |*  1 |  HASH JOIN
14. |*  2 |   TABLE ACCESS FULL| T1   |  2498 | 72442 |    59   (6)| 00:00:01 |  
15. |   3 |   TABLE ACCESS FULL| T2   | 49954 |   536K|   159   (2)| 00:00:02 |  
16. ---------------------------------------------------------------------------
17.   
18. Predicate Information (identified by
19. ---------------------------------------------------
20.   
21. "T1"."OBJECT_ID"="T2"."OBJECT_ID")  
22. "T1"."OBJECT_NAME" LIKE '%T1%')  
23.   
24. 统计信息  
25. ----------------------------------------------------------
26.           0  recursive calls  
27.           0  db block gets  
28.         932  consistent gets  
29.           0  physical reads  
30. size
31. to
32. from
33. to/from
34.           0  sorts (memory)  
35.           0  sorts (disk)  
36. rows


这里省略了SELECT出来的具体数据,但是我们关心的是返回的结果行数、执行计划以及逻辑读这些信息。
首先从执行计划可以看到,这条SQL语句在2个表上都是全表扫描。在第1个表T1上,有 like ‘%T1%’这样的条件,导致只能全表扫描,这没有问题。但是第2个表,也是全表扫描,这里有没有问题呢?或者说是有没有优化的余地,答案显然是肯定的。
这里的问题在于执行计划ID=1的那一行,Oracle优化器评估T1 like ‘%T1%’返回的结果行数为2498行,即T1表总行数的5%,如果2个表采用index range scan+nested loop连接,oracle评估的成本会高于full table scan+hash join。下面可以看到Oracle优化器评估的index range_scan+nested loop的成本:

1. SQL> explain plan for select /*+ use_nl(t1 t2) index(t2) */ t1.*,t2.owner   
2. from
3. where t1.object_name like '%T1%'
4. and
5.   
6. 已解释。  
7.   
8. SQL> @showplan  
9.   
10. PLAN_TABLE_OUTPUT  
11. --------------------------------------------------------------------------------------
12. Plan hash value: 3787413387  
13. --------------------------------------------------------------------------------------
14. | Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time
15. --------------------------------------------------------------------------------------
16. |   0 | SELECT
17. |   1 |  TABLE ACCESS BY INDEX
18. |   2 |   NESTED LOOPS              |        |  2498 | 99920 |  5061   (1)| 00:01:01 |  
19. |*  3 |    TABLE ACCESS FULL
20. |*  4 |    INDEX
21. --------------------------------------------------------------------------------------
22. Predicate Information (identified by
23. ---------------------------------------------------
24. "T1"."OBJECT_NAME" LIKE '%T1%')  
25. "T1"."OBJECT_ID"="T2"."OBJECT_ID")


从执行计划可以看到Oracle优化器评估的成本为5061,远远高于原来的219。
但是实际的逻辑读是多少呢?




1. 统计信息  
2. ----------------------------------------------------------
3.           0  recursive calls  
4.           0  db block gets  
5.         290  consistent gets  
6.           0  physical reads  
7. size
8. to
9. from
10. to/from
11.           0  sorts (memory)  
12.           0  sorts (disk)  
13. rows


加了HINT之后实际的逻辑读只有290,低于原始SQL的932。所以这里可以看出来,由于Oracle优化器过高地估计了T1表经过like操作过滤返回的行数,也就过高地估计了nest loop的成本,最终也就选择了不是最优的执行计划。

下面我们用Oracle的SQL Tuning Advisor来尝试这条SQL:


1. SQL> var tuning_task varchar2(100);  
2. SQL> DECLARE
3.   2    l_sql_id v$session.prev_sql_id%TYPE;  
4.   3    l_tuning_task VARCHAR2(30);  
5. BEGIN
6. '4zbqykx89yc8v';  
7.   6    l_tuning_task := dbms_sqltune.create_tuning_task(sql_id => l_sql_id);  
8.   7    :tuning_task:=l_tuning_task;  
9.   8    dbms_sqltune.execute_tuning_task(l_tuning_task);  
10.   9    dbms_output.put_line(l_tuning_task);  
11. END;  
12.  11  /  
13. 任务_74  
14.   
15. PL/SQL 过程已成功完成。  
16.   
17. SQL> print tuning_task;  
18.   
19. TUNING_TASK  
20. ---------------------------------------------------------------------------------------------------------
21. 任务_74  
22.   
23. SQL> SELECT dbms_sqltune.report_tuning_task(:tuning_task) FROM
24.   
25. DBMS_SQLTUNE.REPORT_TUNING_TASK(:TUNING_TASK)  
26. --------------------------------------------------------------------------------
27. GENERAL INFORMATION SECTION
28. -------------------------------------------------------------------------------
29. Tuning Task Name
30. Tuning Task Owner                 : TEST1  
31. Scope                             : COMPREHENSIVE  
32. Time
33. Completion Status                 : COMPLETED  
34. Started at
35. Completed at
36. Number of
37.   
38. -------------------------------------------------------------------------------
39. Schema Name: TEST1  
40. SQL ID     : 4zbqykx89yc8v  
41. SQL Text   : select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%'
42. and
43.   
44. -------------------------------------------------------------------------------
45. FINDINGS SECTION
46. -------------------------------------------------------------------------------
47.   
48. 1- SQL Profile Finding (see explain plans section
49. --------------------------------------------------------
50.  为此语句找到了性能  
51.   
52.   Recommendation (estimated benefit: 46.62%)  
53. ------------------------------------------
54.   -考虑接受推荐的 SQL  
55. '任务_74', replace
56. TRUE);  
57.   
58. -------------------------------------------------------------------------------
59. EXPLAIN PLANS SECTION
60. -------------------------------------------------------------------------------
61.   
62. 1- Original With
63. ------------------------------
64. Plan hash value: 1838229974  
65.   
66. ---------------------------------------------------------------------------
67. | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time
68. ---------------------------------------------------------------------------
69. |   0 | SELECT
70. |*  1 |  HASH JOIN
71. |*  2 |   TABLE ACCESS FULL| T1   |    29 |   841 |    59   (6)| 00:00:01 |  
72. |   3 |   TABLE ACCESS FULL| T2   | 49954 |   536K|   159   (2)| 00:00:02 |  
73. ---------------------------------------------------------------------------
74.   
75. Predicate Information (identified by
76. ---------------------------------------------------
77.   
78. "T1"."OBJECT_ID"="T2"."OBJECT_ID")  
79. "T1"."OBJECT_NAME" LIKE '%T1%')  
80.   
81. 2- Using SQL Profile  
82. --------------------
83. Plan hash value: 3787413387  
84.   
85. --------------------------------------------------------------------------------------
86. | Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time
87. --------------------------------------------------------------------------------------
88. |   0 | SELECT
89. |   1 |  TABLE ACCESS BY INDEX
90. |   2 |   NESTED LOOPS              |        |    29 |  1160 |   117   (3)| 00:00:02  
91.  |  
92. |*  3 |    TABLE ACCESS FULL
93. |*  4 |    INDEX
94. --------------------------------------------------------------------------------------
95.   
96. Predicate Information (identified by
97. ---------------------------------------------------
98.   
99. "T1"."OBJECT_NAME" LIKE '%T1%')  
100. "T1"."OBJECT_ID"="T2"."OBJECT_ID")  
101.   
102. -------------------------------------------------------------------------------


上面代码中的sql_id是从v$sql来,对应的是没有加hint的SQL。
结果看起来非常棒,SQL Tuning Advisor为我们找到了理想的执行计划,T1表上经过谓词过滤后返回的行数评估为29,相当地精确。我们要做的就是Accept SQL Profile,接受这个SQL Profile。


1. SQL> execute dbms_sqltune.accept_sql_profile(task_name => :tuning_task,replace => TRUE,force_match=>true);  
2.   
3. PL/SQL 过程已成功完成。


那么我们再执行其他的类似SQL看看:


1. SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T2%' and
2.   
3. 已选择77行。  
4.   
5. 执行计划  
6. ----------------------------------------------------------
7. Plan hash value: 3787413387  
8. --------------------------------------------------------------------------------------
9. | Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time
10. --------------------------------------------------------------------------------------
11. |   0 | SELECT
12. |   1 |  TABLE ACCESS BY INDEX
13. |   2 |   NESTED LOOPS              |        |    29 |  1160 |   117   (3)| 00:00:02 |  
14. |*  3 |    TABLE ACCESS FULL
15. |*  4 |    INDEX
16. --------------------------------------------------------------------------------------
17. Predicate Information (identified by
18. ---------------------------------------------------
19. "T1"."OBJECT_NAME" LIKE '%T2%')  
20. "T1"."OBJECT_ID"="T2"."OBJECT_ID")  
21. Note  
22. -----
23. "SYS_SQLPROF_014b39f084c88000" used for
24.   
25. 统计信息  
26. ----------------------------------------------------------
27.           1  recursive calls  
28.           0  db block gets  
29.         343  consistent gets  
30.           0  physical reads  
31. size
32. to
33. from
34. to/from
35.           0  sorts (memory)  
36.           0  sorts (disk)  
37. rows

这一次,尽管我们更改了LIKE 后面的值,但是执行计划与SQL Tuning Advisor产生的执行计划完全一样。从执行计划的”Note“一节也可以看到,SQL Profile起作用了。SQL Profile的名字为”SYS_SQLPROF_014b39f084c88000″。



1. SQL> select name,category,signature,type,status,force_matching from
2.   
3. NAME                           CATEGORY                                   SIGNATURE TYPE      STATUS  FOR
4. ------------------------------ ------------------------------ --------------------- --------- ---------- ---
5. SYS_SQLPROF_014b39f084c88000   DEFAULT


一些复杂的SQL,我经常会先通过SQL Tuning Advisor来分析一下,看能不能让Oracle自已找出一个更好的执行计划。

我们来看看,SQL Profiles实际上是些什么:



1. SQL< select * from
2.   
3.             SIGNATURE CATEGORY                            ATTR# ATTR_VAL  
4. --------------------- ------------------------------ ---------- ----------------------------------------
5. DEFAULT                                 1 OPT_ESTIMATE(@"SEL$1", TABLE, "T1"@"SEL$
6.                                                                 1", SCALE_ROWS=0.01161091426)


从sys.sqlprof$attr这个数字字典里面,我们可以看到两样东西:signature和attr。
signature是什么?可以理解为与sql_id、sql_hash_value类似的值,用来标识SQL。在10g以上的版本中,查看v$sql的定义就可以发现2列:exact_matching_signature、force_matching_signature。通过下面的数据可以看出区别:



1. SQL> select rownum,a.* from
2. select
3. from v$sql where sql_text like '%/*%xjs%' and sql_text not like '%v$sql%' order by
4.   
5.     ROWNUM EXACT_MATCHING_SIGNATURE FORCE_MATCHING_SIGNATURE PLAN_HASH_VALUE SQL_TEXT  
6. ---------- ------------------------ ------------------------ --------------- --------------------------------------------------
7. select /* xjs */ object_name    from T1 where
8. 't1'
9.   
10. select /* xjs */ object_name    from T1 where
11.                                                                              um<=3  
12.   
13. select /* xjs   */ object_name    from T1 where
14.                                                                              wnum<=3  
15.   
16. select /* xjs */ 2 from t1 where
17. select /* xjs */ 1 from t1 where
18. select /* xjs */ object_name    from T1 where
19. 'T1'
20.   
21. select /* xjs */ object_name    from T1 where
22.                                                                              um<=1  
23.   
24. select /* xjs */ OBJECT_NAME from T1 where
25.                                                                              =1  
26.   
27. SELECT /* xjs */ object_name    from T1 where
28.                                                                              um<=1  
29.   
30. select /* xjs */ object_name from t1 where
31.                                                                              =1


从上面的数据可以看出:

  • 第2、3条SQL的exact_matching_signature相同,第7、8、9、10条SQL的exact_matching_signature相同。
  • 第2、3条SQL的force_matching_signature相同,第4、5条SQL的force_matching_signature相同,第7、8、9、10条的SQL的force_matching_signature相同。第1、6条SQL的force_matching_signature相同

有如下的结论:对SQL语句,去掉重复的空格(不包括字符常量),将大小写转换成相同,比如均为大写(不包括字符常量)后,如果SQL相同,那么SQL语句的exact_matching_signature就是相同的。对SQL语句,去掉重复的空格(不包括字符常量),将大小写转换成相同,比如均为大写(不包括字符常量),然后去掉SQL中的常量,如果SQL相同,那么SQL语句的force_matching_signature就是相同的。但是例外的情况是:如果SQL中有绑定变量,force_matching_signature就会与exact_matching_signature一样的生成标准。




1. SQL> select rownum,a.* from
2. (select
3. from v$sql where sql_text like '%/*%xjs2%' and sql_text not like '%v$sql%' order by
4.   
5.     ROWNUM EXACT_MATCHING_SIGNATURE FORCE_MATCHING_SIGNATURE PLAN_HASH_VALUE SQL_TEXT  
6. ---------- ------------------------ ------------------------ --------------- --------------------------------------------------
7. select /* xjs2 */ object_name    from T1 where
8. 'T1' and
9.   
10. select /* xjs2 */ object_name    from t1 where
11. 'T1' and
12.   
13. select /* xjs2 */ object_name    from t1 where
14. 'T2' and


可以看到,现在exact_matching_signature与force_matching_signature完全一样了。
从force_matching_signature的特性,我们可以想到一个用途,用于查找没有使用绑定变量的SQL语句,类似于使用plan_hash_value来查找。

回到前面,accept_sql_profile这个过程,force_match参数设为TRUE,那么dba_sql_profiles中的signature则是由SQL的force_matching_signature而来,否则便是exact_matching_signature。对于Outlines来说,则只能是exact_matching_signature。从这个角度上讲,Sql Profiles比Outlines的使用范围更广,因为Sql profiles对没有使用绑定变量的SQL也支持得很好。值得注意的是,Sql profiles的force_match属性是不能更改的,只能在创建时指定,如果要更改,则只能重新创建改Sql Profile。

下面来看看sys.sqlprof$attr数据字典。这里面没有SQL Profile的名字,而是用的sql的signature。大家从attr_val的结果发现了什么?



1. OPT_ESTIMATE(@"SEL$1", TABLE, "T1"@"SEL$1", SCALE_ROWS=0.01161091426)


可以看到,SQL Profiles的attr_val实际上就是一些Hints,这跟Outlines没有本质上的区别。只是SQL Profiles中的Hint,没有指定SQL使用哪个索引,也没有指定表的连接方法和连接顺序。这里只指定了T1表评估返回的行数,与原始的评估返回的行数的放大缩小的倍数。2498*0.01161091426正好为29。这里就是告诉Oracle优化器,T1表经过谓语过滤后返回行数应该为评估的0.01161091426倍。从这里可以看出,SQL Profiles并不会锁定SQL的执行计划,只是提供了更多、更准确的统计信息给优化器。看下面的测试:




1. SQL> exec dbms_stats.set_table_stats('TEST1','T1',numrows=>5000000);  
2.   
3. PL/SQL 过程已成功完成。  
4. SQL> explain plan for select
5. from
6. where t1.object_name like '%T1%'
7. and
8.   
9. 已解释。  
10.   
11. SQL> @showplan  
12.   
13. PLAN_TABLE_OUTPUT  
14. ----------------------------------------------------------------------------------
15. Plan hash value: 1838229974  
16. ---------------------------------------------------------------------------
17. | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time
18. ---------------------------------------------------------------------------
19. |   0 | SELECT
20. |*  1 |  HASH JOIN
21. |*  2 |   TABLE ACCESS FULL| T1   |  2903 | 84187 |   288  (81)| 00:00:04 |  
22. |   3 |   TABLE ACCESS FULL| T2   | 49954 |   536K|   159   (2)| 00:00:02 |  
23. ---------------------------------------------------------------------------
24. Predicate Information (identified by
25. ---------------------------------------------------
26. "T1"."OBJECT_ID"="T2"."OBJECT_ID")  
27. "T1"."OBJECT_NAME" LIKE '%T1%')  
28. Note  
29. -----
30. "SYS_SQLPROF_014b39f084c88000" used for


将T1表的统计信息中的表行数改为500万,Oracle就会评估为返回5000000*5%*0.01161091426=2903行。这里执行计划又变回为full scan+hash join。可以看到,虽然SQL Profile起作用了,但是并没有锁定执行计划。

小结:本文简单介绍了什么是SQL Profiles及其作用,如何使用SQL Tuning Advisor来生成SQL Profile,以及生成的SQL Profile产生的Hint。同时也介绍了SQL的signature。

下一篇将会介绍如何手工来为创建、生成SQL Profile,以及如何让SQL Profile也能像Outlines一样锁定SQL的执行计划,以保持SQL执行计划的稳定性。






举报

相关推荐

0 条评论