hive中的mapjoin

今天遇到一個hive的問題,以下hive sql:sql

select f.a,f.b from A t join B f  on ( f.a=t.a and f.ftime=20110802)  app

該語句中B表有30億行記錄,A表只有100行記錄,並且B表中數據傾斜特別嚴重,有一個key上有15億行記錄,在運行過程當中特別的慢,並且在reduece的過程當中遇有內存不夠而報錯。優化

爲了解決用戶的這個問題,考慮使用mapjoin,mapjoin的原理:內存

MapJoin簡單說就是在Map階段將小表讀入內存,順序掃描大表完成Join。
上圖是Hive MapJoin的原理圖,出自Facebook工程師Liyin Tang的一篇介紹Join優化的slice,從圖中能夠看出MapJoin分爲兩個階段:
經過MapReduce Local Task,將小表讀入內存,生成HashTableFiles上傳至Distributed Cache中,這裏會對HashTableFiles進行壓縮。
MapReduce Job在Map階段,每一個Mapper從Distributed Cache讀取HashTableFiles到內存中,順序掃描大表,在Map階段直接進行Join,將數據傳遞給下一個MapReduce任務。開發

MAPJION會把小表所有讀入內存中,在map階段直接拿另一個表的數據和內存中表數據作匹配,因爲在map是進行了join操做,省去了reduce運行的效率也會高不少test

這樣就不會因爲數據傾斜致使某個reduce上落數據太多而失敗。因而原來的sql能夠經過使用hint的方式指定join時使用mapjoin。效率

select /*+ mapjoin(A)*/ f.a,f.b 
from A t join B f  
on ( f.a=t.a and f.ftime=20110802) 

再運行發現執行的效率比之前的寫法高了好多。原理

mapjoin還有一個很大的好處是可以進行不等鏈接的join操做,這種操做若是直接使用join的話語法不支持不等於操做,hive語法解析會直接拋出錯誤。若是把不等於寫到where裏會形成笛卡爾積,數據異常增大,速度會很慢。甚至會任務沒法跑成功~。select

根據mapjoin的計算原理,MAPJION會把小表所有讀入內存中,在map階段直接拿另一個表的數據和內存中表數據作匹配。這種狀況下即便笛卡爾積也不會對任務運行速度形成太大的效率影響。map

並且hive的where條件自己就是在map階段進行的操做,因此在where裏寫入不等值比對的話,也不會形成額外負擔。

如此看來,使用MAPJOIN開發的程序僅僅使用map一個過程就能夠完成不等值join操做,效率還會有很大的提高。

例子:

select /*+ MAPJOIN(a) */ a.start_level, b.* 
from dim_level a join (select * from test) b
 where b.xx>=a.start_level and b.xx<end_level;

簡單總結一下,mapjoin的使用場景:

1. 關聯操做中有一張表很是小

2.不等值的連接操做

相關文章
相關標籤/搜索