参考资料:
本系列博客主要参考资料有CUUG冉乃纲老师数据库教学笔记,《SQL优化核心思想》(罗炳森,黄超,钟侥著),《PostgreSQL技术内幕:查询优化深度探索》(张树杰著),排名不分先后。
4 Filter转换
4.1 环境准备
create table tests1 as select * from dba_objects;
create table tests2 as select * from tests1;
CREATE INDEX IX_tests1_ID ON tests1(OBJECT_ID);
CREATE INDEX IX_tests2_ID ON tests2(OBJECT_ID);
4.2 Filter说明及初步改善
下面请大家执行一下这条SQL
EXPLAIN PLAN FOR SELECT COUNT(*) FROM tests1 T1
WHERE EXISTS (SELECT 1
FROM tests2 T2
WHERE T1.OBJECT_TYPE=T2.OBJECT_TYPE
AND T2.OWNER='SCOTT'
UNION ALL
SELECT 1 FROM tests2 T3
WHERE T1.OBJECT_ID=T3.OBJECT_ID
AND T3.OBJECT_TYPE='DIRECTORY');
首先解释什么是Filter,Filter的计算方法类似嵌套循环,即外表走一条,子查询执行一次,子查询依赖外表,但是于嵌套循环不同的是,嵌套循环是结果集和结果集(当然这个被驱动的最好是表或者物化视图,因为可以走索引)的连接方式,可以理解为连接的两端都是固定的结果集,而Filter是结果集和查询的嵌套循环,被驱动部分无法构成一个独立的结果集。SQL优化器本身一般也是不太喜欢Filter,在产生执行计划时尽量展开Filter,上面的SQL之所以产生Filter,就是因为传入的条件不一样,优化器没法展开。
我们加上hint unnest试一下,强制让Filter展开,
EXPLAIN PLAN FOR SELECT COUNT(*) FROM tests1 T1
WHERE EXISTS (SELECT /*+ UNNEST*/ 1
FROM tests2 T2
WHERE T1.OBJECT_TYPE=T2.OBJECT_TYPE
AND T2.OWNER='SCOTT'
UNION ALL