问题描述
我使用的是 Hive 2.3.5 Spark 2.3.3 版本
当我在 hive 上运行以下查询时,它失败了...说试图扫描太多分区。
select t1.A,t2.B
from t1 left join t2 on t1.x = t2.x
where t1.x = 'abc'
与我运行时相比,它工作正常:
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'?
正常连接无需额外过滤器即可正常工作,但不允许连接
解决方法
优化器并不总是可以下推谓词,因为它不够智能。并且 WHERE 最有可能在 join 之后被应用,导致扫描太多行。 可能 PPD 与 INNER JOIN 一起工作得很好。 EXPLAIN 计划可能会提供有关计划的更多信息。
但除此之外,还有一个问题。
你是说 INNER join 工作正常...看:
您的两个查询完全不同。第一个是LEFT JOIN。如果 t2 不包含 t2.x = 'abc' 的行,它将返回来自 t1 的行。
第二个有不同的行为,它是一个 INNER JOIN,实际上是因为 where 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