谓词下推与 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。
在 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。