连接谓语推入
连接谓词推入(JoinPredicatePushdown)是优化器处理带视图的目标SQL的另外一种优化手段,它是指虽然优化器还是会把该SQL中视图的定义SQL语句当作一个独立的处理单元来单独执行,但此时优化器会把原本处于该视图外部査询中和该视图之间的连接条件推入到该视图的定义SQL语句内部,这样做是为了能使用上该视图内部相关基表上的索引,进而能走出基于索引的嵌套循环连接。和之前介绍的各种查询转换一样,连接谓词推入使优化器在选择目标SQL的执行计划时多出了走基于索引的嵌套循环连接这种选择,这就增加了走出更高效执行计划的可能性。
但是请注意,连接谓词推入所带来的基于索引的嵌套循环连接并不一定能走出更高效的执行计划,因为当做了连接谓词推入后,原目标SQL中的视图就和外部査询产生了关联,同时Oracle又必须将该视图的定义SQL语句当作一个独立的处理单元来单独执行,这也就意味着对于外部查询所在结果集中的每一条记录,上述视图的定义SQL语句都得单独执行一次,这样一旦外部査询所在结果集的Cardinality比较大的话,即便在执行上述视图的定义SQL语句时能用上索引,整个SQL的执行效率也不一定会比不做连接谓词推入时的哈希连接或排序合并连接髙。所以,Oracle在做连接谓词推入时会考虑成本,只有当经过连接谓词推入后走嵌套循环连接的等价改写SQL的成本值小于原SQL的成本值时,Oracle才会对目标SQL做连接谓词推入。
Oracle是否能做连接谓词推入与目标视图的类型、该视图与外部查询之间的连接类型以及连接方法有关。到目前为止,Oracle仅仅支持对如下类型的视图做连接谓词推入。
(1)视图定义SQL语句中包含UNIONALL/UNION的视图
(2)视图定义SQL语句中包含DISTINCT的视图
(3)视图定义SQL语句中包含GROUP BY的视图
(4)和外部查询之间的连接类型是外连接的视图
(5)和外部查询之间的连接方法是反连接的视图
(6)和外部查询之间的连接方法是半连接的视图
连接因式分解
连接因式分解(Join Factorization)是优化器处理带UNIONALL的目标SQL的一种优化手段,它是指优化器在处理以UNIONALL连接的目标SQL的各个分支时,不再原封不动地分别重复执行每个分支,而是会把各个分支中公共的部分提出来作为一个萆独的结果集,然后再和原UNIONALL中剩下的部分做表连接。连接因式分解在OraclellgR2中才被引入,它的好处是显而易见的。如果不把UNIONALL中公共的部分提出来,则意味着这些公共部分中所包含的表会在UNIONALL的各个分支中被重复访问;而连接因式分解则能够在最大程度上避免这种重复访问现象的产生,当UNIONALL的公共部分所包含的表的数据量很大时,即便是只减少一次对大表的重复访问,那也意味着执行效率上的巨大提升。
在Oracle11gR2及其后续的版本中,即使由于在视图定义SQL语句中包含了集合运算符UNIONALL而导致Oracle不能对其做视图合并,Oracle也不一定会把该视图的定义SQL语句当作一个整体来单独执行,因为此时Oracle还可能会对其做连接因式分解。这里需要注意的是,Oracle对包含UNIONALL的目标SQL做连接因式分解的前提条件是,连接因式分解后的等价改写SQL和原SQL在语义上完全等价,如果不能满足这一点,那么Oracle就不会做连接因式分解。
表扩展
表扩展(TableExpansion)是优化器处理针对分区表的目标SQL的一种优化手段,它是指当目标SQL中分区表的某个局部分区索引由于某种原因在某些分区上变得不可用(索引状态为UNUSABLE)时,Oracle能将原目标SQL等价改写成按分区UNIONALL的形式,这样除了那些不可用的分区所对应的UNIONALL分支之外,其他分区所对应的UNIONALI:分支还是可以正常使用该局部分区索引。
我们都知道,当查询的数据只是全部数据中的少部分时,使用索引确实能极大提高查询的速度,但索引的维护必然会同时减慢相关DML操作的执行速度,所以使用索引是有副作用的。有的系统的业务特点就是要尽可能快地往目标表的当前分区中导入数据,其修改的数据也仅限于该表中处于当前分区的活动数据,同时还会有针对目标表的査询,这个査询并不局限于当前分区。针对这种类型的系统,为了尽可能快地对当前分区执行DML操作,往往人为地把当前分区的局部分区索引的状态设为UNUSABLE,这样就省去了对当前分区执行DML操作时同步维护相关局部分区索引的成本,所以这样做是能够提高相关DML操作的速度的。但现在的问题是,在OraclellgR2之前,这样做会导致所有原本可以使用该局部分区索引的査询语句都无法正常使用该局部分区索引。。