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

Sql 左加入配置单元在执行扫描之前未通过筛选器,sql,apache-spark,hive,left-join,hiveql,Sql,Apache Spark,Hive,Left Join,Hiveql,我正在使用Hive2.3.5 Spark版本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 t

我正在使用Hive2.3.5 Spark版本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上执行join时,为什么还要在表t2上再次通过显式过滤器(t2.x='abc') 其中t1.x='abc'


正常连接在不需要额外过滤器的情况下可以正常工作,但不允许连接

Optimizer因为不够智能而不总是能够下推谓词。最有可能的情况是,join之后应用了WHERE,从而导致扫描太多行。 可能PPD与内部联接配合得很好。解释计划可能会提供有关计划的更多信息

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

你是说内部连接工作正常。。。看:

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

第二个有不同的行为,它实际上是一个内部连接,因为where
t2.x='abc'
中的这个谓词不允许空值,过滤掉没有与t2连接的记录。选中该选项,您将选择仅联接记录=内部联接。若表中不包含t2.x='abc'的行,则第二个查询将不会返回任何行

尝试将一个连接条件添加到ON而不是WHERE,这看起来更像左连接:

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
另一种方法是在联接之前在子查询中使用筛选

   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

Optiimizer并不总是能够下推谓词,因为它不够智能。最有可能的情况是,join之后应用了WHERE,从而导致扫描太多行。 可能PPD与内部联接配合得很好。解释计划可能会提供有关计划的更多信息

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

你是说内部连接工作正常。。。看:

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

第二个有不同的行为,它实际上是一个内部连接,因为where
t2.x='abc'
中的这个谓词不允许空值,过滤掉没有与t2连接的记录。选中该选项,您将选择仅联接记录=内部联接。若表中不包含t2.x='abc'的行,则第二个查询将不会返回任何行

尝试将一个连接条件添加到ON而不是WHERE,这看起来更像左连接:

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
另一种方法是在联接之前在子查询中使用筛选

   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

当我在较小的DB/dataset上运行时,我的两个查询(有t2.x=‘abc’和没有t2.x=‘abc’)都能正常工作,并给出完全相同的结果。但是如果没有谓词,查询将在完整大小的数据集上失败。您的建议会起作用,但我们不想添加此谓词两次..因为此查询是自动生成的,将来可能会在其他列上中断,@PuneetGarg您可能会对结果感到满意。但它不像左连接那样工作。如果仔细检查,您将看到WHERE和t2.x='abc'中存在该谓词将其转换为内部联接。您将永远无法从t1中选择t2中没有相应连接行的行。如果您对内部联接感到满意,只需显式地使用它。相同的结果意味着行已连接。如果您在某些情况下确实需要左连接功能,那么第二个查询将出错。它的工作原理与内部联接相同。只要在t2中没有数据的情况下进行测试,就不会返回任何行。当我在较小的DB/数据集上运行时,这两个查询(有t2和没有t2.x='abc')都会给出完全相同的结果。但是如果没有谓词,查询将在完整大小的数据集上失败。您的建议会起作用,但我们不想添加此谓词两次..因为此查询是自动生成的,将来可能会在其他列上中断,@PuneetGarg您可能会对结果感到满意。但它不像左连接那样工作。如果仔细检查,您将看到WHERE和t2.x='abc'中存在该谓词将其转换为内部联接。您将永远无法从t1中选择t2中没有相应连接行的行。如果您对内部联接感到满意,只需显式地使用它。相同的结果意味着行已连接。如果您在某些情况下确实需要左连接功能,那么第二个查询将出错。它的工作原理与内部联接相同。只需在t2中缺少数据的情况下进行测试,就不会返回任何行