我有3个小表:smallTable0
,smallTable1
和smallTable3
。他们都有不到100行和相同的模式。我也有3个大表:largeTable0
,largeTable1
和largeTable3
。全部有超过1M行,具有相同的模式,与小表共享id
列,除id
以外的其他分区(如果分区很重要,我怀疑它不会)。蜂巢不MapJoin对两个大表的联盟小表
设置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;
它运行良好,但使用通用连接而不是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。但是,如果是这种情况,我预计会加入smallTable0
到smallTable1 UNION ALL smallTable2
以产生一个通用连接。
由于Hive中的错误,我的代码中的错误,Hive中的缺失功能或者我的误解,这是否是奇怪的行为?