一、hive.groupby.skewindata
set hive.groupby.skewindata=true;
數據傾斜時負載均衡,當選項設定為true,生成的查詢計划會有兩個MRJob。第一個MRJob 中,Map的輸出結果集合會隨機分布到Reduce中,每個Reduce做部分聚合操作,並輸出結果,這樣處理的結果是相同的GroupBy Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的;第二個MRJob再根據預處理的數據結果按照GroupBy Key分布到Reduce中(這個過程可以保證相同的GroupBy Key被分布到同一個Reduce中),最后完成最終的聚合操作。

由上圖下部分過程可看到過程,由此帶出解決數據傾斜的方式。
二、關於數據傾斜出現原因:
- 對於join過程來說,如果出項較多的key值為空或異常的記錄,或key值分布不均勻,就容易出現數據傾斜。
- 對於group by 過程來說,如果某一個key值有特別的多的記錄,其它key值的記錄比較少,也容易出項數據傾斜。
Join實現原理舉例:
select name, orderidf
from user t1
join order t2 on t1.uid=t2.uid
Group by實現原理舉例
sql = select rank, isonline, count(1)
from city
group by 1, 2
三、數據傾斜的解決方案
①、join引起數據傾斜的解決方法
- 如果是由於key值為空或為異常記錄,且這些記錄不能被過濾掉的情況下,可以考慮給key賦一個隨機值,將這些值分散到不同的reduce進行處理。
- 如果是一個大表和一個小表join的話,可以考慮使用mapjoin來避免數據傾斜。
mapjoin原理可參考前一篇文章:淺談Hive中Map Join原理及場景
②、group by 引起數據傾斜的解決方法
set hive.map.aggr=true;
在map中會做部分聚集操作,效率更高但需要更多的內存。開啟map之后使用combiner,這樣基本上是對各記錄比較同質的數據效果比較好,相反,則沒有什么意義。通用的做法是設置下面兩個參數:
set hive.groupby.mapaggr.checkinterval = 100000 (默認)執行聚合的條數
set hive.map.aggr.hash.min.reduction=0.5(默認)
#如果hash表的容量與輸入行數之比超過這個數,那么map端的hash聚合將被關閉,默認是0.5,
#設置為1可以保證hash聚合永不被關閉;

還有一個方式是本文提及的set hive.groupby.skewindata=true
ps: 有博文反應該參數與set hive.map.aggr=true同時使用時候對distinct結果會有影響,但我實測並沒有,可能是特定情況才會出現?如若碰到還請隨時交流。hive.groupby.skewindata 和 hive.map.aggr 組合的坑
參考:
學習交流,有任何問題還請隨時評論指出交流。