基于Oracle的SQL优化--学习(十七)

表移除

   表移除是优化器处理带多表连接的目标SQL的一种优化手段,它是指优化器会把虽然在目标SQL中存在,但是其存在与否对最终执行结果没有影响的表从该目标SQL中移除,这样优化器至少可以少做一次表连接,进而就能提高原目标SQL的执行效率。

Oracle如何处理SQL语句中的IN

   优化器在处理带IN的目标SQL时,可能也会用到査询转换,也即本节要介绍的IN-ListExpansion(又称为ORExpansion,两者等价)。为了能让大家明白IN-ListExpansion的优缺点,本节除了会介绍IN-ListExpansion之外,还会介绍优化器在处理带IN的目标SQL时可能会使用的其他方法。在Oracle数据库里,IN和OR是等价的,优化器在处理带IN的目标SQL时实际上会将其转换为带OR的等价改写SQL,也就是说,本节介绍的处理带IN的目标SQL的方法也同样适用于带OR的目标SQL。

    优化器在处理带IN的目标SQL时,通常会采用如下这四种方法:
    (1)使用IN-List Iterator。
    (2)使用IN-List Expansion。
    (3)使用IN-List Filter。
    (4)对IN做子査询展开,或者既做子查询展开又做视图合并。

IN-List Iterator

    IN-List Iterator是针对IN后面是常量集合的一种处理方法。此时优化器会遍历目标SQL中IN后面的常量集合中的每一个值,然后去做比较,看目标结果集中是否存在和这个值匹配的记录。如果存在匹配记录,则这个记录就会成为该SQL的最终返回结果集中的一员;如果不存在匹配记录,则优化器会继续遍历IN后面的常量集合中的下一个值,直到该常量集合遍历完毕。
关于IN-ListIterator,有如下几点需要注意:
(1)IN-ListIterator是Oracletf对目标SQL的IN后面是常量集合的首选处理方法,它的处理效率通常都会比IN-ListExpansion高。

(2)Oracle能用IN-ListIterator来处理IN的前提条件是IN所在的列上一定要有索引。

(3)不能强制让Oracle走IN-ListIterator类型的执行计划,Oracle里也没有相关的强制走IN-ListIterator的Hint,但可以通过联合设置10142和10157事件来禁掉IN-ListIterator。

IN-List Expansion/OR Expansion

   IN-List Expansion/OR Expansion(IN-List Expansion又称为OR Expansion,两者等价)是针对IN后面是常量集合的另外一种处理方法,它是指优化器会把目标SQL中IN后面的常量集合拆开,把里面的每个常量都提出来形成一个分支,各分支之间用UNIONALL来连接,即IN-ListExpansion的本质是把带IN的目标SQL等价改写成以UNIONALL连接的各个分支。

    IN-List Expansion的好处是改写成以UNIONALL连接的分支后,各个分支就可以各自走索引、分区修剪(PartitionPruning)、表连接等相关的执行计划而互不干扰。它的坏处是未做IN-ListExpansion之前优化器只需要解析一个目标SQL并决定其执行计划,而一旦做了IN-ListExpansion后优化器就要对等价改写后的每一个UNIONALL分支都执行同样的解析、决定执行计划的工作,也就是说,等价改写后的目标SQL的解析时间会随着UNIONALL分支的递增而递增。这意味着当IN后面的常量集合所包含的元素数量非常多的时候,做IN-ListExpansion仅解析的时间可能就会非常长,这就是IN-ListIterator通常会比FN-ListExpansion的效率高的原因。正是基于上述原因,做了IN-ListExpansion的等价改写SQL的执行效率并不一定会比原SQL高,这也就意味着IN-ListExpansion—定也是基于成本的,即只有当经过IN-ListExpansion后的等价改写SQL的成本值小于原SQL的成本值时,Oracle才会对目标SQL执行IN-ListExpansion。

IN-List Filter

    IN-List Filter是针对IN后面是子查询的一种处理方法,优化器会把IN后面的子査询所对应的结果集当作过滤条件,并且走FILTER类型的执行计划IN后面是子查询,意味着IN后面是变量的集合;走的是FILTER类型的执行计划,意味着Oracle并没有对IN后面的子査询做子查询展幵。所以,能走IN-ListFiltei类型的执行计划就意味着目标SQL要满足如下两个条件:

    (1)目标SQL的IN后面是子査询而不是常量的集合。
    (2)Oracle未对目标SQL的IN后面的子査询做子査询展开。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值