我有 3 张小桌子:smallTable0
、smallTable1
和smallTable3
。它们都有不到 100 行和相同的模式。我还有 3 张大桌子:largeTable0
、largeTable1
和largeTable3
。所有这些都有超过 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。但是,如果是这种情况,我会期望加入smallTable0
会smallTable1 UNION ALL smallTable2
导致共同加入。
奇怪的行为是 Hive 中的错误、我的代码中的错误、Hive 中缺少的功能还是我的误解造成的?