hive數(shù)據(jù)傾斜解決

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é))

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容