2013-05-03 31 views
0

我有3个小表:smallTable0,smallTable1smallTable3。他们都有不到100行和相同的模式。我也有3个大表:largeTable0largeTable1largeTable3。全部有超过1M行,具有相同的模式,与小表共享id列,除id以外的其他分区(如果分区很重要,我怀疑它不会)。蜂巢不MapJoin对两个大表的联盟小表

设置hive.auto.convert.join=true后,有下列情形导致MapJoin,符合市场预期:

  • 加入smallTable0smallTable1
  • 加入smallTable0largeTable0
  • 加入smallTable0smallTable1 UNION ALL smallTable2

以下情况不会导致在一个MapJoin,如预期的那样:

  • 加入largeTable0反对任何事情。
  • 加入smallTable0反对任何与hive.auto.convert.join=false

不料但是,下面的情况下也不会导致MapJoin:

  • 加入smallTable0largeTable0 UNION ALL largeTable1

准确的查询是如下:

SELECT * FROM smallTable0 s 
JOIN (
    SELECT * FROM (
    SELECT * FROM largeTable0 
    UNION ALL 
    SELECT * FROM largeTable1 
) x 
) l 
    ON s.id = l.id; 

它运行良好,但使用通用连接而不是MapJoin,导致性能下降。创建代表largeTable0 UNION ALL largeTable1的视图不能解决问题。我确定创建一个表largetTable0 UNION ALL largeTable1可以解决问题,但重复这么多的数据,然后保持同步是不可取的。

联盟运营商的源代码(here)有一个评论,我觉得有点神秘。

/** 
* Union operators are not allowed either before or after a explicit mapjoin hint. 
* Note that, the same query would just work without the mapjoin hint (by setting 
* hive.auto.convert.join to true). 
**/ 
@Override 
public boolean opAllowedBeforeMapJoin() { 
    return false; 
} 

@Override 
public boolean opAllowedAfterMapJoin() { 
    return false; 
} 

这似乎表明,UNION操作是不允许有一个明确的暗示MapJoin,但是,联盟允许操作员与活动开始hive.auto.convert.join结果MapJoins。不过,我不明白为什么会允许另一个被禁止。除非“仅仅工作”意味着查询将“工作”,而不是用MapJoin。但是,如果是这种情况,我预计会加入smallTable0smallTable1 UNION ALL smallTable2以产生一个通用连接。

由于Hive中的错误,我的代码中的错误,Hive中的缺失功能或者我的误解,这是否是奇怪的行为?

回答

1

您可以指定Hive在连接期间处理表。我总是指定MAPJOINSTREAMTABLE如果我知道一个小表是否适合连接,或者是应该流式传输给其他人的非常大的表。

例如

SELECT /*+ MAPJOIN(smalltable0) */ * FROM smallTable0 s