我有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
结合
- 加入
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提示中是不允许的,但是在hive.auto.convert.join
启动的MapJoin中允许使用UNION操作符。然而,我不明白为什么一个会被允许,另一个不被允许。除非"just work"意味着查询将"工作",而不是使用MapJoin。但是,如果是这种情况,我希望将smallTable0
连接到smallTable1 UNION ALL smallTable2
会导致Common Join。
奇怪的行为是Hive的错误,我的代码中的错误,Hive中缺少的功能,还是我的误解?
您可以指定Hive在连接期间处理表的提示。如果我知道一个小表是连接的候选表,或者一个应该流到其他表的非常大的表,我总是指定MAPJOIN或STREAMTABLE。
。
SELECT /*+ MAPJOIN(smalltable0) */ * FROM smallTable0 s