Hive不会针对两个大表的Union对一个小表进行MapJoin



我有3个小表:smallTable0, smallTable1smallTable3。它们都少于100行,并且模式相同。我还有3个大表:largeTable0largeTable1largeTable3。它们都有超过1M的行,具有相同的模式,与小表共享id列,并且在id以外的其他地方进行分区(如果分区重要,我怀疑它没有)。

在设置了hive.auto.convert.join=true之后,下列情况会导致MapJoin,如预期的那样:

  • 加入smallTable0smallTable1
  • 加入smallTable0largeTable0
  • smallTable0smallTable1 UNION ALL smallTable2的联合

以下情况不会像预期的那样导致MapJoin:

  • 加入largeTable0对抗任何事物
  • smallTable0hive.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;

它运行得很好,但是使用Common Join而不是MapJoin,这会导致性能下降。创建一个代表largeTable0 UNION ALL largeTable1的视图并不能解决这个问题。我确信创建一个largetTable0 UNION ALL largeTable1表可以解决这个问题,但是复制这么多数据,然后保持它们同步是不可取的。

Union操作符的源代码(这里)有一个注释,我觉得有点神秘。

/**
* 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启动的MapJoin中允许使用UNION操作符。然而,我不明白为什么一个会被允许,另一个不被允许。除非"just work"意味着查询将"工作",而不是使用MapJoin。但是,如果是这种情况,我希望将smallTable0连接到smallTable1 UNION ALL smallTable2会导致Common Join。

奇怪的行为是Hive的错误,我的代码中的错误,Hive中缺少的功能,还是我的误解?

您可以指定Hive在连接期间处理表的提示。如果我知道一个小表是连接的候选表,或者一个应该流到其他表的非常大的表,我总是指定MAPJOINSTREAMTABLE

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

最新更新