hive在跑數(shù)據(jù)時經(jīng)常會出現(xiàn)數(shù)據(jù)傾斜的情況。使的作業(yè)經(jīng)常reduce時卡住較長時間,有時完成任務(wù)的百分百比甚至?xí)赝?,如果你碰到這種情況,”恭喜“你,你遇到數(shù)據(jù)傾斜了。
以下是幾種常見的數(shù)據(jù)傾斜場景:
1、join的key值發(fā)生傾斜,key值包含很多空值或是異常值
這種情況可以對異常值賦一個隨機值來分散key
如:
select a.uuid,count(1)
from dw_space_dau_orc_dt a
join(
select case when uuid is null then cast(rand(47)*100000as int) uuid
from dw_space_clean_orc_dt
) b on a.uuid=b.uuid
通過rand函數(shù)將為null的值分散到不同的值上,在key值比較就能解決數(shù)據(jù)傾斜的問題
注:對于異常值如果不需要的話,最好是提前過濾掉,這樣計算量可以大大減少
2、當(dāng)key值都是有效值時,解決辦法為設(shè)置以下幾個參數(shù)
set hive.exec.reducers.bytes.per.reducer = 1000000000
也就是每個節(jié)點的reduce 默認(rèn)是處理1G大小的數(shù)據(jù),如果你的join 操作也產(chǎn)生了數(shù)據(jù)傾斜,那么你可以在hive 中設(shè)定
set hive.optimize.skewjoin = true;
set hive.skewjoin.key = skew_key_threshold (default = 100000)
hive 在運行的時候沒有辦法判斷哪個key 會產(chǎn)生多大的傾斜,所以使用這個參數(shù)控制傾斜的閾值,如果超過這個值,新的值會發(fā)送給那些還沒有達到的reduce, 一般可以設(shè)置成你
(處理的總記錄數(shù)/reduce個數(shù))的2-4倍都可以接受.
傾斜是經(jīng)常會存在的,一般select 的層數(shù)超過2層,翻譯成執(zhí)行計劃多于3個以上的mapreduce job 都很容易產(chǎn)生傾斜,建議每次運行比較復(fù)雜的sql 之前都可以設(shè)一下這個參數(shù). 如果你不知道設(shè)置多少,可以就按官方默認(rèn)的1個reduce 只處理1G 的算法,那么 skew_key_threshold = 1G/平均行長. 或者默認(rèn)直接設(shè)成250000000 (差不多算平均行長4個字節(jié))
3、reduce數(shù)太少
set mapred.reduce.tasks=800;
默認(rèn)是先設(shè)置hive.exec.reducers.bytes.per.reducer這個參數(shù),設(shè)置了后hive會自動計算reduce的個數(shù),因此兩個參數(shù)一般不同時使用
4、對于group by 產(chǎn)生傾斜的問題
set hive.map.aggr=true (開啟map端combiner); //在Map端做combiner,假如map各條數(shù)據(jù)基本上不一樣, 聚合沒什么意義,做combiner反而畫蛇添足,hive里也考慮的比較周到通過參數(shù)hive.groupby.mapaggr.checkinterval = 100000 (默認(rèn))
hive.map.aggr.hash.min.reduction=0.5(默認(rèn))
兩個參數(shù)的意思是:預(yù)先取100000條數(shù)據(jù)聚合,如果聚合后的條數(shù)/100000>0.5,則不再聚合
set hive.groupby.skewindata=true;//決定groupby操作是否支持傾斜的數(shù)據(jù)。注意:只能對單個字段聚合.控制生成兩個MR Job,第一個MR Job Map的輸出結(jié)果隨機分配到reduce做次預(yù)匯總,減少某些key值條數(shù)過多某些key條數(shù)過小造成的數(shù)據(jù)傾斜問題
5、小表與大表關(guān)聯(lián)
此時,可以通過mapjoin來優(yōu)化,
sethive.auto.convert.join=true; //將小表刷入內(nèi)存中
sethive.mapjoin.smalltable.filesize = 2500000 ;//刷入內(nèi)存表的大小(字節(jié))