谓词下推 vs On 子句
Posted
技术标签:
【中文标题】谓词下推 vs On 子句【英文标题】:Predicate Pushdown vs On Clause 【发布时间】:2019-09-17 11:41:53 【问题描述】:当在 Hive 中执行连接,然后使用 where 子句过滤输出时,Hive 编译器将尝试在连接表之前过滤数据。这称为谓词下推 (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
如果启用了下推谓词 (hive.optimize.ppd),则表 a 中 some_name = 6 的行将在执行连接之前被过滤。
不过,我最近也了解到,在将一个表与另一个表连接之前,还有另一种过滤数据的方法(https://vinaynotes.wordpress.com/2015/10/01/hive-tips-joins-occur-before-where-clause/)。
可以在ON子句中提供条件,在join之前会过滤表a
例如:
SELECT * FROM a JOIN b ON a.some_id=b.some_other_id AND a.some_name=6
这两个都提供谓词下推优化吗?
谢谢
【问题讨论】:
【参考方案1】:两者都是有效的,在 INNER JOIN 和 PPD 的情况下,两者的工作方式相同。但是在 OUTER JOINS 的情况下,这些方法的工作方式不同
ON 加入条件在加入之前起作用。
WHERE 在加入后应用。
优化器决定谓词下推是否适用,它可能会起作用,但在 LEFT 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
会限制NULL,LEFT JOIN
会被转化为INNER JOIN
,因为如果b.some_name=6,就不能为NULL。
PPD 不会改变这种行为。
如果您添加额外的 OR 条件允许在右表中使用 NULL,您仍然可以使用 WHERE 过滤器执行 LEFT JOIN:
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 条件,因为它在连接之前过滤右表,此查询按预期工作且易于理解:
SELECT * FROM a
LEFT JOIN b ON a.some_id=b.some_other_id and b.some_name=6
PPD 仍然适用于 ON 过滤器,如果表 b 是 ORC,PPD 会将谓词推送到 ORC 读取器的最低级别,并将使用内置 ORC 索引在三个级别上进行过滤:行、条带和文件。
更多关于同一主题和一些测试:https://***.com/a/46843832/2700344
因此,无论 PPD 还是非 PPD,如果可能,最好使用带有 ON 条件和 ON 过滤的显式 ANSI 语法,以使查询尽可能简单,并避免无意中转换为 INNER JOIN。
【讨论】:
以上是关于谓词下推 vs On 子句的主要内容,如果未能解决你的问题,请参考以下文章