【问题标题】:Predicate Pushdown vs On Clause谓词下推 vs On 子句
【发布时间】: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

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

谢谢

【问题讨论】:

    标签: join hive left-join hiveql on-clause


    【解决方案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://stackoverflow.com/a/46843832/2700344

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

    【讨论】:

      猜你喜欢
      • 2016-05-06
      • 2019-01-21
      • 1970-01-01
      • 2019-06-18
      • 1970-01-01
      • 2022-01-01
      • 2010-11-04
      • 2020-02-02
      • 2011-02-20
      相关资源
      最近更新 更多