我有3个小表:smallTable0
,smallTable1
和smallTable3
。它们都有少于100行和相同的模式。我还有3个大表:largeTable0
,largeTable1
和largeTable3
。所有行都有超过1M行,具有相同的模式,与小表共享id
列,在id
之外的其他内容上进行分区(如果分区很重要,我怀疑它没有)。
设置hive.auto.convert.join=true
后,以下情况会产生MapJoin,如预期的那样:
smallTable0
加入smallTable1
smallTable0
加入largeTable0
smallTable0
<{1}} 以下情况不会像预期的那样导致MapJoin:
smallTable1 UNION ALL smallTable2
反对任何事情。largeTable0
smallTable0
然而,出乎意料的是,以下情况也不会导致MapJoin:
hive.auto.convert.join=false
加入smallTable0
确切的查询如下:
largeTable0 UNION ALL largeTable1
它运行正常,但使用Common Join而不是MapJoin,它会导致性能下降。创建表示SELECT * FROM smallTable0 s
JOIN (
SELECT * FROM (
SELECT * FROM largeTable0
UNION ALL
SELECT * FROM largeTable1
) x
) l
ON s.id = l.id;
的视图无法解决问题。我确定创建一个largeTable0 UNION ALL largeTable1
表可以解决问题,但是重复这么多数据然后保持它们同步是不可取的。
Union运算符的源代码(here)有一条评论,我觉得有点神秘。
largetTable0 UNION ALL largeTable1
似乎暗示UNION运算符不允许使用显式MapJoin提示,但允许使用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;
}
会启动MapJoins。但是我不明白为什么允许另一个人被禁止。除非“正常工作”意味着查询将“正常”,而不是使用MapJoin。但是,如果是这种情况,我原本希望将hive.auto.convert.join
加入smallTable0
以产生公共加入。
奇怪的行为是Hive中的错误,我的代码中的错误,Hive中缺少的功能,还是我的误解?
答案 0 :(得分:1)
您可以为Hive指定提示,以便在连接期间处理表。我总是指定 MAPJOIN 或 STREAMTABLE ,如果我知道小表是否适合加入,或者是非常大的表应该流式传输到其他表。
e.g。
SELECT /*+ MAPJOIN(smalltable0) */ * FROM smallTable0 s