出现的原因:
子查询(in/exists/not in/not exists)没能展开(unnest),在执行计划中就会产生FILTER
FILTER类型的执行计划,先对驱动表返回多少行的数据,子查询扫描后就对多少行的数据进行过滤,优化器可能要执行多少次的子查询
优化方法:
子查询非嵌套(Subquery Unnesting):当where 子查询中有in、not in、exists、not exists
等,CBO 会尝试将子查询展开(unnest),从而消除FILTER,这个过程就叫作子查询非嵌套,子查询非嵌套的目的就是消除FILTER
1、使用HINT(UNNEST),一般很难做到
2、等价改写SQL
哪些SQL 写法容易产生FILTER 呢?
当子查询语句含有exists 或者not exists 时,子查询中有固化子查询关键词(union/union all/start with connect by/rownum/cube/rollup),那么执行计划中就容易产生FILTER
1、子查询中有固化关键字(union/union all/start with connect by/rownum/cube/rollup),子查询会被固化为一个整体,采用exists/not exists 这种写法,
这时子查询中有主表连接列,只能是主表通过连接列传值给子表,所以CBO 只能选择FILTER
2、SQL 改写为in/not in 这种写法,子查询虽然被固化为整体,但是子查询中没有主表连接列字段,这个时候CBO 就不会选择FILTER
视图合并:
当SQL 语句中有内联视图(in-line view,from 后面的子查询),或者SQL 语句中有用create view 创建的视图,CBO 会尝试将内联视图/视图拆开,进行等价的改写,这个过程就叫作视图合并。
判断是否发生视图合并:
没有发生视图合并,在执行计划中,我们可以看到VIEW关键字,而且视图/子查询会作为一个整体。
发生了视图合并,那么视图/子查询就会被拆开,而且执行计划中视图/子查询部分就没有VIEW 关键字
影响:
视图合并之后,有可能会打乱视图/子查询中表的原本连接顺序:
现象:单独执行子查询a,速度非常快,单独执行子查询b,速度也非常快,但是把上面两个子查询组合在一起,速度反而很慢
处理方法:
1、添加HINT:no_merge 禁止视图合并,
2、也可以让子查询a 与子查询b 进行HASH 连接,当子查询a 与子查询b 进行HASH 连接之后,就不会发生视图合并了。
(子查询a 与子查询b 进行HASH 连接之后,会自动地把子查询a 与子查询b 作为一个整体。因为HASH 连接不传值)
select /*+ use_hash(a,b) */ … from () a,() b where a.id=b.id;
3、子查询非嵌套一样,当视图中有固化子查询关键字的时候,就不能发生视图合并,固化子查询的关键字包括union、union all、start with connect by、rownum、cube、rollup




