谓词下推与 On 子句

Predicate Pushdown vs On Clause

在 Hive 中执行连接然后使用 where 子句过滤输出时,Hive 编译器将尝试在连接 table 之前过滤数据。这称为谓词下推 (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

来自 table 的具有 some_name = 6 的行将在执行连接之前被过滤,如果下推谓词已启用(hive.optimize.ppd)。

不过,我最近还了解到,还有另一种方法可以在将 table 中的数据与另一个 table(https://vinaynotes.wordpress.com/2015/10/01/hive-tips-joins-occur-before-where-clause/).

合并之前过滤数据

可以在ON子句中提供条件,tablea会在join执行前被过滤

例如:

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

这两个都提供谓词下推优化吗?

谢谢

两者都有效,并且在 INNER JOIN 和 PPD 的情况下,两者的工作方式相同。但是这些方法在 OUTER JOINS

情况下的工作方式不同

ON 加入条件在加入前有效。

加入后应用WHERE。

优化器决定 Predicate 下推是否适用,它可能会起作用,但是在 LEFT JOIN 的情况下,例如右边有 WHERE 过滤器 table,WHERE 过滤器

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

会限制NULL,LEFT JOIN会转化为INNER JOIN,因为如果b.some_name=6,就不能为NULL。

并且 PPD 不会更改此行为。

如果您在右侧添加允许 NULL 的额外 OR 条件,您仍然可以使用 WHERE 过滤器执行 LEFT JOIN table:

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 过滤器的 LEFT JOIN 不需要额外的 OR 条件,因为它在连接前向右 table 过滤,此查询按预期工作且易于理解:

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

PPD 仍然适用于 ON 过滤器,如果 table b 是 ORC,PPD 会将谓词推送到 ORC reader 的最低可能级别,并将使用内置的 ORC 索引进行过滤在三个级别上:行、条纹和文件。

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

因此,无论 PPD 与否,如果可能,最好使用带有 ON 条件和 ON 过滤的显式 ANSI 语法,以保持查询尽可能简单并避免无意中转换为 INNER JOIN。