在执行扫描之前,左加入配置单元未通过筛选器



我使用的是配置单元2.3.5Spark 2.3.3版

当我在配置单元上运行以下查询时,它失败了。。说试图扫描太多分区。

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"?

正常联接在不需要额外过滤器的情况下工作良好,但不允许联接

Optiimizer并不总是能够下推谓词,因为它不够智能。并且WHERE很可能是在联接之后应用的,导致扫描太多行。可能PPD与INNER JOIN配合得很好。EXPLAIN计划可能会提供有关该计划的更多信息。

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

你是说INNER加入工作正常…看:

您的两个查询完全不同。第一个是LEFT 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

最新更新