我有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中的缺失功能或者我的誤解,這是否是奇怪的行爲?