Join 谓词下推vs On子句

Join 谓词下推vs On子句,join,hive,left-join,hiveql,on-clause,Join,Hive,Left Join,Hiveql,On Clause,在配置单元中执行联接,然后使用where子句过滤输出时,配置单元编译器将尝试在联接表之前过滤数据。这称为谓词下推() 例如: SELECT * FROM a JOIN b ON a.some_id=b.some_other_id WHERE a.some_name=6 SELECT * FROM a JOIN b ON a.some_id=b.some_other_id AND a.some_name=6 如果启用了下推谓词(hive.optimize.ppd),则表a中某些_name=6

在配置单元中执行联接,然后使用where子句过滤输出时,配置单元编译器将尝试在联接表之前过滤数据。这称为谓词下推()

例如:

SELECT * FROM a JOIN b ON a.some_id=b.some_other_id WHERE a.some_name=6
SELECT * FROM a JOIN b  ON a.some_id=b.some_other_id AND a.some_name=6
如果启用了下推谓词(hive.optimize.ppd),则表a中某些_name=6的行将在执行联接之前进行筛选

但是,我最近还了解到,在将表与另一个表连接之前,还有另一种方法可以过滤表中的数据()

可以在ON子句中提供条件,并且在执行联接之前将筛选表a

例如:

SELECT * FROM a JOIN b ON a.some_id=b.some_other_id WHERE a.some_name=6
SELECT * FROM a JOIN b  ON a.some_id=b.some_other_id AND a.some_name=6
这两者都提供谓词下推优化吗


谢谢

这两种方法都是有效的,如果使用内部连接和PPD,这两种方法将同样有效。但是这些方法在外部联接的情况下工作方式不同

ON join条件在join之前起作用

连接后应用于何处

优化器决定谓词下推是否适用,它可能会工作,但在左连接的情况下,例如右表上的WHERE过滤器,WHERE过滤器

SELECT * FROM a 
             LEFT JOIN b ON a.some_id=b.some_other_id 
 WHERE b.some_name=6 --Right table filter
将限制空值,
左连接
将转换为
内部连接
,因为如果b.some_name=6,它不能为空。

和PPD不会改变这种行为。

如果在右表中添加其他或允许空值的条件,则仍然可以使用WHERE筛选器执行左连接:

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将把谓词推到ORC读取器的最低级别,并使用内置的ORC索引在三个级别上进行过滤:行、条带和文件

关于同一主题和一些测试的更多信息:

因此,不管是PPD还是非PPD,如果可能的话,最好使用带有ON条件和ON筛选的显式ANSI语法,以使查询尽可能简单,并避免无意中转换为内部联接