连接 predicate 下推vs on子句

7vhp5slm  于 2021-06-24  发布在  Hive
关注(0)|答案(1)|浏览(291)

在配置单元中执行联接,然后使用where子句过滤输出时,配置单元编译器将尝试在联接表之前过滤数据。这称为 predicate 下推(http://allabouthadoop.net/what-is-predicate-pushdown-in-hive/)
例如:

SELECT * FROM a JOIN b ON a.some_id=b.some_other_id WHERE a.some_name=6

如果启用了下推 predicate (hive.optimize.ppd),则在执行联接之前,将筛选表a中某些\u name=6的行。
不过,我最近还了解到,在将表与另一个表连接之前,还有另一种方法可以过滤表中的数据(https://vinaynotes.wordpress.com/2015/10/01/hive-tips-joins-occur-before-where-clause/).
可以在on子句中提供条件,在执行联接之前,表a将被过滤
例如:

SELECT * FROM a JOIN b  ON a.some_id=b.some_other_id AND a.some_name=6

这两种方法都提供 predicate 下推优化吗?
谢谢您

5tmbdcev

5tmbdcev1#

两者都是有效的,在内部连接和ppd的情况下,两者的工作原理相同。但是这些方法在外部连接的情况下工作方式不同
on join条件在join之前起作用。
连接后应用于何处。
优化器决定 predicate 下推是否适用,它可能工作,但在左连接的情况下,例如右表上的where过滤器,where过滤器

SELECT * FROM a 
             LEFT JOIN b ON a.some_id=b.some_other_id 
 WHERE b.some_name=6 --Right table filter

将限制空值,并且 LEFT JOIN 将转化为 INNER JOIN ,因为如果b.some_name=6,则不能为空。
ppd不会改变这种行为。
如果在右表中添加了允许空值的附加条件或条件,则仍然可以使用where filter执行左联接:

SELECT * FROM a 
             LEFT JOIN b ON a.some_id=b.some_other_id 
 WHERE b.some_name=6 OR b.some_other_id IS NULL --allow not joined records

如果您有多个具有许多这样的过滤条件的连接,那么这样的逻辑会使您的查询难以理解并减少错误。
带on filter的left join不需要附加or条件,因为它在联接前过滤右表,此查询按预期工作,易于理解:

SELECT * FROM a 
             LEFT JOIN b ON a.some_id=b.some_other_id and b.some_name=6

ppd仍然适用于on filter,如果表b是orc,ppd将把 predicate 推到orc读取器的最低级别,并使用内置的orc索引在三个级别上进行过滤:行、条带和文件。
更多关于同一主题和一些测试:https://stackoverflow.com/a/46843832/2700344
因此,不管是ppd还是非ppd,如果可能的话,最好使用带有on条件和on筛选的显式ansi语法,以使查询尽可能简单,并避免无意中转换为内部连接。

相关问题