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 默認是處理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è)置多少假哎,可以就按官方默認的1個reduce 只處理1G 的算法,那么? skew_key_threshold? = 1G/平均行長. 或者默認直接設(shè)成250000000 (差不多算平均行長4個字節(jié))
3鞍历、reduce數(shù)太少
set?mapred.reduce.tasks=800;
默認是先設(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 (默認)
hive.map.aggr.hash.min.reduction=0.5(默認)
兩個參數(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é))