繁体   English   中英

谓词下推 vs On 子句

[英]Predicate Pushdown vs On Clause

在 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-子句/ )。

可以在ON子句中提供条件,表a将在执行联接之前进行过滤

例如:

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。

优化器决定谓词下推是否适用,它可能会起作用,但在 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 不会改变这种行为。

如果在右表中添加允许 NULL 的额外 OR 条件,您仍然可以使用 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

如果您有多个连接和许多这样的过滤条件,这样的逻辑会使您的查询难以理解和错误修剪。

LEFT JOIN with ON filter 不需要额外的 OR 条件,因为它在 join 之前过滤了右表,这个查询按预期工作并且易于理解:

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 : //stackoverflow.com/a/46843832/2700344

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM