')
OUTLINE_DH_TEST OPT_PARAM('_optimizer_extended_cursor_sharing' 'no
OUTLINE_DH_TEST OPT_PARAM('_bloom_filter_enabled' 'false')
OUTLINE_DH_TEST OPT_PARAM('_optimizer_null_aware_antijoin' 'false'
OUTLINE_DH_TEST OPT_PARAM('_optim_peek_user_binds' 'false')
OUTLINE_DH_TEST DB_VERSION('11.2.0.1')
OUTLINE_DH_TEST OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
OUTLINE_DH_TEST IGNORE_OPTIM_EMBEDDED_HINTS
15 rows selected. 注意: 不指定outline类别是,默认为default,而且此处创建时,不能指定为default类别(会报错)。这个方法不是很方便,因为必须将整个SQL文本作为语句的一部分,可能导致语句无法共享等问题,因此很少使用这种方法
3、从10g起,可以通过引用共享池中已经存在的SQL语句来创建outline exec DBMS_OUTLN.create_outline(hash_value=>1752921103,child_number => 0,category=>'test'); 注意 这种方法不能指定outline的具体名字,由系统自动生成,可以通过alter outline SYS_OUTLINE_14061114223605901 rename to dh_test2修改不指定类别的话默认为default,而且此处创建时,不能指定为default类别(会报错)。我们使用outline固定执行计划时,一般都是选用此种方法后面有一个简单示例,可以加深理解
二、修改outline
1、更改outline名称 alter outline SYS_OUTLINE_14061114223605901 rename to dh_test2
2、更改outline类别 exec dbms_outln.update_by_cat(oldcat=>'DDD',newcat=>'DEFAULT');
3、重建outline alter outline DH_TEST2 rebuild;
三、激活outline Oracle优化器只会考虑激活的outline,这意味着如果创建的outline没有被激活,Oracle根本不会使用它,一个outline必须满足如下两个条件才能被激活:
1、outline必须处于可用状态(创建时默认就是可用,一般不会有问题),修改方法,alter outline DH_TEST2 disable;
2、类别必须通过初始化参数use_stored_ouotlines在会话或者系统级激活,可以设置为“TRUE/FALSE/类别名”三种,其中TRUE表示启用default类别 alter session set use_stored_outlines=TRUE;
四、移动outline 只能通过将数据字典中保存的hint数据复制到另一个数据库的数据字典,除此之外没有其它办法。不过还好这个方法也非常简单,因为outline相关的hint数据都保存在outln用户下的三张表中:ol$、ol$hints、ol$nodes。可以用下面的命令来导入和导出可用的outline exp tables=(outln.ol$,outln.ol$hints,outln.ol$nodes) file=xxx.dmp
五、编辑outline,后续会提供两种方法 当优化器无法为给定的SQL生成高效的执行计划时,可以通过编辑outline来实现,可以理解为修改outline中的hint
1、使用原语句建Outline
2、查看Outline执行计划Select HINT_TEXT,USER_TABLE_NAME,JOIN_PRED,cardinality,bytes,cost
from OUTLN.OL$HINTS
where ol_name = 'OLXXXXX_ORIG'
3、在SQL上加hint,执行语句(注意语句结构不能改变,不能增加或删除查询块什么的)
?4、查看加上hint的SQL语句,执行计划是否与我们期望的一致
5、得到期望的执行计划后,将两个outline的执行计划进行互换,即完成outline的编辑! UPDATE OUTLN.OL$HINTS
SET OL_NAME = DECODE(OL_NAME,
'OLXXXXX_MOD',
'OLXXXXX_ORIG',
'OLXXXXX_ORIG',
'OLXXXXX_MOD')
WHERE OL_NAME IN ('OLXXXXX_MOD', 'OLXXXXX_ORIG');
6、启用outline
六、删除outline
可以用如下命令分别删除指定的outline或者某个类别下的所有outline drop outline dh_test1; dbms_outln.drop_by_cat(cat=>'test');
示例一(引用使用共享池中的SQL来创建outline) SQL> create table dh_stat as select rownum id ,object_name name ,object_type type from dba_objects; SQL> create index ind_1 on dh_stat(id) compute statistics; SQL> alter system flush shared_pool;
系统已更改。
SQL> exec DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'dbmon',TABNAME=>'dh_stat',ESTIMATE_PERCENT=>30,METHOD_OPT=>'FOR ALL COLUMNS SIZE 1',NO_INVALIDATE=>FALSE,CASCADE=>TRUE,DEGREE => 1);
PL/SQL 过程已成功完成。
SQL> col name format a15
SQL> col name format a30
SQL> col sql_text format a55 给运行的语句添加一个独特的注释,方便后续查找语句
SQL> select /* outlinetest1 */ * from dh_stat where id=771;
ID NAME TYPE
---------- ------------------------------ ---------------
771 APPLY$_CONF_HDLR_COLUMNS_UNQ1 INDEX
SQL> select sql_text,sql_id,hash_value,child_number from v$sql a where sql_text like '%outlinetest1%' and sql_text not like '%v$sql%';
SQL_TEXT SQL_ID HASH_VALUE CHILD_NUMBER
------------------------------------------------------- ------------- --------