oracle 执行sql路径,如何指定 SQL 执行路径

原标题:如何指定 SQL 执行路径

作者韩涛,来自社区“平台人生”专栏

http://www.talkwithtrend.com/Column/detail/id/11

就像是每个人都会认识一个叫小明的人一样,每个DBA的库中都会存在这样一种SQL。这种SQL所涉及的表上通常有IND1_TABLE和IND2_TABLE两个索引,当使用 IND2_TABLE索引执行SQL时可以很快返回结果,但偏偏ORACLE总是会选择IND1_TABLE来执行SQL。

造成这种情况的大部分原因都是因为相关索引字段的数据分布不平均,且在这些字段上没有收集柱状图造成的(柱状图的特性还不是很稳定,如果开启的话需要特别关注)。这种情况下,一般建议开发人员在编写SQL时就指定好较优的索引;对于已经上线的SQL如果可以修改的话,那么在语句中添加相应的HINT,这个问题马上也可以迎刃而解。

不过可惜,大部分上线的SQL都是不能修改的,即使能够修改,也要经过复杂的测试,所谓远水救不了近火,问题就在眼前,难道真的束手无策了吗?当然不是,在这种危急存亡的时刻,我们至少还有几招必杀技可以用。

一、绑定SQL的执行计划

绑定执行计划的方法有三种outline方式、sql profile方式、baseline方式。这里着重介绍sql profile方式,该方式需要使用到ORACLE内部包dbms_sqltune,具体语法如下:

DBMS_SQLTUNE.IMPORT_SQL_PROFILE (

sql_text => ,//需要绑定语句的具体内容

profile => ,//想要加入的HINT

name => ,//profile的名字

deion => ,//profile的描述

category => 'DEFAULT',//profile的分类,默认为default

validate => TRUE,

replace => TRUE,//如果已经存在同名profile是否替换

force_match => FALSE//TRUE代表强制将SQL中参数转换为绑定变量,FALSE代表不会强制转换SQL参数为绑定变量

)

例如:对于T3表进行操作,当前执行计划如下:

33e330ec770c32ec9849cdbc3a369c0c.png

如果想要通过profile方式,使该语句通过全表扫描的方式执行,我们需要按照以下步骤执行:

1. 取得相对应的HINT

1) explain plan for

select /*+ full(t3) */ count(*) from t3;

2) select * from table(dbms_xplan.display(null,null,'outline'));

得到输出如下:

2854db9d8bd1d428f68a483ba088b664.png

3) 对输出结果进行格式化,将其中单引号‘’,均变为双引号“”后,按照如下格式展现。

6089cdfa420fdb35f03c51617409582d.png

2. 取得对应的sql_text

select sql_fulltext into sql_txt from v$sql wheresql_id='3hmsukzqn2f9t';

3. 执行IMPORT_SQL_PROFILE函数

d4bdb414d372f9d4c3ab7e6970230984.png

4. 查看dba_sql_profiles视图,名字为3hmsukzqn2f9t_profile是不是已经在里面有记录了呢!

select * from dba_sql_profiles;

5. 再次执行select count(*) from t3操作,查看输出执行计划已经改变了吧。

8f398dd713edcefba750f09861fd93a6.png

二、修改表或字段统计信息

上述绑定执行计划的必杀技虽然好用,但是双拳难敌四手,如果语句没有使用绑定变量、或者已经使用绑定变量,但相似SQL数量众多,那绑定的方法可就不太好用了。这个时候,我们还是要靠ORACLE自己来生成我们想要的执行计划。有同学会问了ORACLE不是已经生成了错误的执行计划了吗?怎么可能按照我们的意愿重新生成呢?没有错,什么都不做,ORACLE肯定是不会自动开窍的,但我们知道ORACLE生成执行计划是要参考表和索引上的统计信息的,所以对于没有使用绑定变量或者已经使用绑定变量但SQL数量较多的情况,我们就从统计信息入手。

1. 仍然对于T3表进行操作,当前执行计划如下:

84ade03568101cf17cf726811959a7d4.png

2. IND_T3为建立在T3(id)字段上面的索引,其唯一值如下:

3. 利用ORACLE内部dbms_stats包,修改ID字段的唯一值个数:

execdbms_stats.SET_COLUMN_STATS('TONY','T3','ID',DISTCNT=>5000);

4. 在此查看ID字段唯一值:

5. 再次执行同样的SQL:select * from t3 where id=2,是不是已经走上你想要的索引了呢!

6. 由此可见,对于大量未使用绑定变量的SQL或者已经使用绑定变量,但相似SQL众多的情况,可以考虑修改表或者索引统计信息的方式来引导ORACLE优化器产生较优的执行计划。返回搜狐,查看更多

责任编辑:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值