【问题标题】:Left Join in hive not passing filters before doing a scan在进行扫描之前,左加入配置单元未通过过滤器
【发布时间】:2021-04-13 07:32:18
【问题描述】:

我正在使用 Hive 2.3.5 Spark 2.3.3 版

当我在 hive 上运行以下查询时,它失败了..saying 试图扫描太多分区。

select t1.A, t2.B 
   from t1 left join t2 on t1.x = t2.x
    where t1.x = 'abc'

vs 当我运行它时,它工作正常:

 select t1.A, t2.B 
 from t1 left join t2 on t1.x = t2.x
    where t1.x = 'abc'
    and t2.x = 'abc'

当我已经在 t1.x = t2.x 上进行连接时,为什么我需要再次在表 t2 上传递显式过滤器 (t2.x='abc') 其中 t1.x = 'abc'?

普通连接可以正常工作,不需要额外的过滤器,但不要让连接

【问题讨论】:

    标签: sql apache-spark hive left-join hiveql


    【解决方案1】:

    优化器并不总是可以下推谓词,因为它不够智能。并且最有可能在加入后应用 WHERE,导致扫描太多行。 PPD 可能适用于 INNER JOIN。 EXPLAIN plan 可能会提供有关计划的更多信息。

    但除此之外,还有一个问题。

    你是说 INNER join 工作正常...看:

    您的两个查询完全不同。第一个是左连接。如果 t2 不包含 t2.x = 'abc' 的行,它将返回来自 t1 的行。

    第二个有不同的行为,它是一个INNER JOIN,因为t2.x = 'abc'中的这个谓词不允许NULL,过滤掉没有与t2连接的记录。检查它,您只选择连接记录 = INNER JOIN。如果表中不包含 t2.x = 'abc' 的行,则第二个查询将不会返回任何行。

    尝试在 ON 而不是 WHERE 中再添加一个连接条件,这看起来更像 LEFT JOIN

    select t1.A, t2.B 
     from t1 left join t2 on t1.x = t2.x and t2.x='abc' 
        where t1.x = 'abc'
    

    我并不是说这会解决扫描分区过多的问题,我只是说这将是真正的左连接,而不是内连接,并且谓词将在连接之前应用于 t2。

    另一种方法是在加入前在子查询中使用过滤。

       select t1.A, t2.B 
         from (select * from t1 where t1.x = 'abc') t1 
             left join (select * from t2 where t2.x = 'abc') t2 
                      on t1.x = t2.x
    

    【讨论】:

    • 当我在较小的数据库/数据集上运行时,我的两个查询(有和没有 t2.x = 'abc')都能正常工作,给出完全相同的结果。但如果没有谓词,则查询在完整大小的数据集上会失败。您的建议可行,但我们不想将此谓词添加两次。因为此查询是自动生成的,将来可能会在其他列上中断,
    • @PuneetGarg 您可能对结果感到满意。但它不像左连接那样工作。如果您仔细检查,您会看到 WHERE 中存在此谓词,并且 t2.x = 'abc' 将其转换为 INNER JOIN。您将永远无法从 t1 中选择在 t2 中没有相应连接行的行。如果您对 INNER JOIN 感到满意,请明确使用它。相同的结果意味着加入的行。如果您在某些情况下确实需要左连接功能,那么第二个查询会出错。它的工作原理与 INNER join 相同。只需使用 t2 中不存在的数据进行测试,您将不会返回任何行
    猜你喜欢
    • 2011-10-27
    • 2017-09-01
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 2017-07-29
    • 2021-05-19
    • 2018-08-15
    • 2018-04-01
    相关资源
    最近更新 更多