一句话:所谓谓词下推,就是将尽可能多的判断更贴近数据源,以使查询时能跳过无关的数据。用在SQL优化上来说,就是先过滤再做聚合等操作。
规则的逻辑描述如下:
During Join predicates cannot be pushed past Preserved Row tables( join条件过滤不能下推到保留行表中)
After Join predicates cannot be pushed past Null Supplying tables(where条件过滤不能下推到NULL补充表)
Preserved Row tables | Null Supplying tables | |
Join Predicate | Case J1: Not Pushed | Case J2: Pushed |
Where Predicate | Case W1: Pushed | Case W2: Not Pushed |
总结如下:
• 对于Join(Inner Join)、Full outer Join,条件写在on后面,还是where后面,性能上面没有区别;
• 对于Left outer Join ,右侧的表写在on后面、左侧的表写在where后面,性能上有提高;
• 对于Right outer Join,左侧的表写在on后面、右侧的表写在where后面,性能上有提高;
• 当条件分散在两个表时,谓词下推可按上述结论2和3自由组合;
• 所谓下推,即谓词过滤在map端执行;所谓不下推,即谓词过滤在reduce端执行
注意:如果在表达式中含有不确定函数,整个表达式的谓词将不会被pushed,例如
select a.* from a join b on a.id = b.id
where a.ds = '2022-08-15' and a.create_time = unix_timestamp();
因为unix_timestamp是不确定函数,在编译的时候无法得知,所以,整个表达式不会被pushed,即ds='2022-08-15'也不会被提前过滤。类似的不确定函数还有rand()等。
什么是谓词
predicate push down 翻译为谓词下推,这个翻译很准确,明确的告诉了我们这个操作是一个什么动作,但是为人诟病的是,什么是谓词,结合起来是什么意思,就比较难以理解。
predicate push down 又可以叫做 Filter Push down,这个叫法准确的描述了动作,但没有精准定位什么能被称之为Filter。全局来看,还是predicate push down较为准确。
predicate(谓词)即条件表达式,在SQL中,谓词就是返回boolean值即true和false的函数,或是隐式转换为bool的函数。SQL中的谓词主要有 LKIE、BETWEEN、IS NULL、IS NOT NULL、IN、EXISTS其结果为布尔值,即true或false。
谓词的使用场景:在SELECT语句的WHERE子句或HAVING子句中,确定哪些行与特定查询相关。 ps:并非所有谓词都可以在HAVING子句中使用。
为什么left join where右边表不能下推?
因为结果会不一致,比如a表,1,2,3,b表2,3,4
a left join b where b > 2:
3 3
如果下推,结果是:
1 null
2 null
3 3