Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2766581
  • 博文数量: 389
  • 博客积分: 4177
  • 博客等级: 上校
  • 技术积分: 4773
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-16 23:29
文章分类

全部博文(389)

分类: Oracle

2013-12-21 12:52:02

                                                  通过SQL Profile使用HINT


       在oracle 11g的后续版本中,use_stored_outlines这个参数已经不存在了。意味着我们不能像以前的版本
中使用create outline的方式来为一个sql创建hint,然后使用store outline来固定执行计划这种方式了.在11g中
我们可以通过dbms_sqltune来为一个sql创建sql profile.这种sql profile是由系统来生成的,我们只有选择和不
选择。其实我们可以通过dbms_spm的非公开过程import_sql_profile来达到此目的.


     首先我们得了解什么是sql profile。sql profile是除了标准的统计信息,参数等一系列的额外信息,比如
对额外的统计,手动的hint.通过sql profile中的信息,optimizer能够更加快速和准确的生成执行计划.而正常的
optimzer运行期间,由于受限于时间的限制,可能产生的计划并不是最佳的。后续引进了sql tune advisor,是一种
让optimzer有足够时间来产生各种执行计划的顾问。


   比如我现在创建一个表,并且在在object_id的栏位上创建了一个索引

   
SQL> create table frank.t1  as select * from dba_objects;

Table created.


SQL> create index ix_object_id on t1(object_id);

Index created.

SQL> exec dbms_stats.gather_table_stats(ownname=>'FRANK',tabname=>'T1',cascade=>TRUE);

PL/SQL procedure successfully completed.

 

SQL> select object_name from t1 where object_id=10;

OBJECT_NAME
--------------------------------------------------------------------------------
C_USER#


Plan hash value: 575481074

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1           |     1 |    30 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IX_OBJECT_ID |     1 |       |     1   (0)| 00:00:01 |


 语句正常执行,计划也是最好的,选择的是走索引,如果运行了dbms_sqltune,也会选择是索引.sql profile
可能都不会生成,现在已经是最好的执行计划了。可是我现在并不想这样,我想使用全表扫描的方式.
通过sql profile很方便就可以实现.


 通过import_sql_profile手动增加import_sql_profile
SQL> begin 
  2  dbms_sqltune.import_sql_profile
  3  (name=>'sp_01',
  4   sql_text=>'select object_name from t1 where object_id=10',
  5   replace=>true,
  6   profile=>sqlprof_attr('FULL()) ;
  7   end;
  8  /

PL/SQL procedure successfully completed.


SQL> select object_name from t1 where object_id=10;

OBJECT_NAME
------------------------------------------------------------------------
C_USER#

SQL> select * from table(dbms_xplan.display_cursor(format=>'ALL'));

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------
SQL_ID  31mm3rsbs12s4, child number 0
-------------------------------------
select object_name from t1 where object_id=10

Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |   285 (100)|          |
|*  1 |  TABLE ACCESS FULL| T1   |     1 |    30 |   285   (1)| 00:00:04 |

..............

Note
-----
   - SQL profile sp_01 used for this statement

现在sql语句的执行计划是全表扫描了。在最后note处显示了使用了sql profile sp_01.表
明我们创建的sql profile被使用了.

  在这里最麻烦的sqlprof_attr('FULL()是这里的格式如何写.在mos上的文章
note 215187.1中的sqlt.zip的目录utl中提供了脚本coe_xfr_sql_profile.sql可以生成
这些信息.

先加hint运行我们要改的sql,再通过coe_xfr_sql_profile.sql取出sqlprof_attr数据

SQL> select /*+ FULL(t1) */ object_name from t1 where object_id=10;


SQL> @coe_xfr_sql_profile.sql;

Parameter 1:
SQL_ID (required)

Enter value for 1: 83zu6pbuujtxs


PLAN_HASH_VALUE AVG_ET_SECS
--------------- -----------
     3617692013        .615

Parameter 2:
PLAN_HASH_VALUE (required)

Enter value for 2: 3617692013

Values passed to coe_xfr_sql_profile:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQL_ID         : "83zu6pbuujtxs"
PLAN_HASH_VALUE: "3617692013"

..................................


在当前目录下生成了一个sql脚本.coe_xfr_sql_profile_83zu6pbuujtxs_3617692013.sql,用vi打开.
发现里面存在一段这样的定义,这就是我们需要的数据.

h := SYS.SQLPROF_ATTR(
q'[BEGIN_OUTLINE_DATA]',
q'[IGNORE_OPTIM_EMBEDDED_HINTS]',
q'[OPTIMIZER_FEATURES_ENABLE('11.1.0.7')]',
q'[DB_VERSION('11.1.0.7')]',
q'[ALL_ROWS]',
q'[OUTLINE_LEAF(@"SEL$1")]',
q'[FULL(@"SEL$1" ,
q'[END_OUTLINE_DATA]');

  再通过import_sql_profile,而sql_text则定义原始的sql,或是一些不能修改源代码应用的sql语句.
通过这种方式,我们实现了人为通过hint改变执行计划.

  sql profile中的hint信息都是存放在sys.sqlobj$data中的comp_data的栏位中.以xml格式存储的
也可以通过从这个栏位来获取sqlprof_attr信息

  在11.2的版本中,dbms_spm也提供了一个过程MIGRATE_STORED_OUTLINE,可以把原来的stored outline
迁移到spm中,通过先建立一个stored outline,然后再迁移到spm中,也可以实现在类似的目的.

阅读(5173) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~