0

我有 3 张小桌子:smallTable0smallTable1smallTable3。它们都有不到 100 行和相同的模式。我还有 3 张大桌子:largeTable0largeTable1largeTable3。所有这些都有超过 1M 的行,具有相同的模式,id与小表共享列,被分区在其他东西上id(如果分区很重要,我怀疑它没有)。

设置后hive.auto.convert.join=true,以下情况会按预期生成 MapJoin:

  • 加入smallTable0反对smallTable1
  • 加入smallTable0反对largeTable0
  • 加入smallTable0反对smallTable1 UNION ALL smallTable2

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

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

然而,出乎意料的是,以下情况也不会导致 MapJoin:

  • 加入smallTable0反对largeTable0 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 提示,但 UNION 运算符允许使用 MapJoin 作为hive.auto.convert.join. 但是我不明白为什么一个会被允许另一个不允许。除非“正常工作”意味着查询将“工作”,而不是使用 MapJoin。但是,如果是这种情况,我会期望加入smallTable0smallTable1 UNION ALL smallTable2导致共同加入。

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

4

1 回答 1

1

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

例如

SELECT /*+ MAPJOIN(smalltable0) */ * FROM smallTable0 s
于 2013-05-07T14:08:34.537 回答