About me:Oracle ACE pro,optimistic,passionate and harmonious. Focus on ORACLE,MySQL and other database programming,peformance tuning,db design, j2ee,Linux/AIX,Architecture tech,etc
全部博文(169)
分类: Oracle
2020-06-10 16:18:20
为什么会形成FILTER操作?(多子节点,单子节点纯粹过滤操作)
FILTER形成于查询转换期间,如果对于子查询无法进行 unnest转换来消除子查询,则会走FILTER,走FILTER说明子查询是受外表结果驱动,类似循环操作!很显然,如果驱动的次数越多,效率越低!
查询转换是能够生成高效SQL执行计划的重要步骤,查询转换不能做好,后面的很多执行路径就没法走了。掌握查询转换机制,对如何写高效的SQL,调优SQL至关重要,了解的越深,对CBO就越了解。下面是CBO组件图,熟悉对应组件是SQL优化必须的内容:
1)FILTER什么时候高效?
FILTER本身会构建HASH表来保存输入/输出对,以备后续减少子查询执行次数,这是与纯粹NESED LOOPS操作的典型区别,比如from a where a.statusIn(select b.staus from b…) 如果status前面已经查过,则后续不需要再次执行子查询,而是直接从保存的HASH表中获取结果,这样减少了子查询执行次数,从而提高效率。也就是说,如果子查询关联条件的重复值很多,FILTER还是有一定的优势,否则就是灾难!
2)FILTER与push_subq hints
如果走FILTER则子查询是受制于子查询外结果集驱动,也就是子查询是最后执行,但是实际有时候子查询应该先执行效率更好,这时候可以使用push_subq hints。
简化前面的语句关键部分如下:
Oracle内部改写如下,无法unnest,如果unnest:
执行计划如下:
从执行计划里可以看到,FILTER多子节点一般有如下特点:
1) 自动生成的绑定变量:B1,因为需要执行循环操作
2) 转为EXISTS
所以以后看到有自动生成的绑定变量的执行计划,都是类似FILTER的操作,比如标量子查询,UPDATE关联子查询,优化的话,都需要干掉(类)FILTER来优化。
这里的例子其实是一个CBO的限制:
含有OR的子查询,经常性无法unnest,Oracle大多无法给转换成UNION/UNION ALL形式的查询
所以,针对这样的语句优化:
1.改写为UNION/UNION ALL形式
2.根据语义、业务含义彻底重写
也就是说,需要重构查询,消除FILTER!慢的根源如下,这里7万多行,只执行了116行打印的执行计划!Id=3~6的执行次数依赖于Id=2的结果行数,id=3~6全表扫描次数太多。