HIVE 資料傾斜

2021-09-25 08:21:05 字數 3573 閱讀 8132

解決資料傾斜,歸根結底是使map的輸出資料更均勻的分布到reduce中去。

1、join

(1)其中乙個表較小,但是key集中。分發到某乙個或幾個reduce上的資料遠高於平均值

(2)大表與大表,但是分桶的判斷欄位0值或空值過多。這些空值都由乙個reduce處理,非常慢

2、group by

group by 維度過小,某值的數量過多。導致處理某值的reduce非常耗時

3、count(distinct)

某特殊值過多,處理此特殊值的reduce耗時

hive.map.aggr=

true

map 端部分聚合,相當於combiner

hive.groupby.skewindata=

true

由於group by 引起資料傾斜的時候進行負載均衡。當選項設定為 true,生成的查詢計畫會有兩個 mr job。第乙個 mr job 中,map 的輸出結果集合會隨機分布到 reduce 中,每個 reduce 做部分聚合操作,並輸出結果,這樣處理的結果是相同的

group

bykey 有可能被分發到不同的 reduce 中,從而達到負載均衡的目的;第二個 mr job 再根據預處理的資料結果按照 group

bykey 分布到 reduce 中(這個過程可以保證相同的 group

bykey 被分布到同乙個 reduce 中),最後完成最終的聚合操作。

set hive.optimize.skewjoin=true;

如果是join 過程出現傾斜,應該設定為true

(1)空值產生的資料傾斜

場景:如日誌中的user_id有些為空(很多),如果取其中的 user_id 和 使用者表中的user_id 關聯,會碰到資料傾斜的問題。

解決方案1:user_id為空的不參與關聯

select

*from

loga

join

users b

on a.user_id

isnot

null

and a.user_id

= b.user_id

union

allselect

*from

loga

where a.user_id

isnull;

解決方案2:賦與空值新的key值(隨機數)

select

*from

loga

left

outer

join

users b

oncase

when a.user_id

isnull

then concat(『hive』,rand() ) else a.user_id

end= b.user_id;

結論:方法2比方法1效率更好,不但io少了,而且作業數也少了。解決方法1中 log讀取兩次,jobs是2。解決方法2 job數是1 。這個優化適合無效 id (比如 -99 , 』』, null 等) 產生的傾斜問題。把空值的 key 變成乙個字串加上隨機數,就能把傾斜的資料分到不同的reduce上 ,解決資料傾斜問題。

(2)不同資料型別關聯產生資料傾斜

場景:使用者表中user_id欄位為int,log表中user_id欄位既有string型別也有int型別。當按照user_id進行兩個表的join操作時,預設的hash操作會按int型的id來進行分配,這樣會導致所有string型別id的記錄都分配到乙個reducer中。

解決方案:把數字型別轉換成字串型別

select

*from

users a

left

outer

join

logs b

on a.usr_id =

cast(b.user_id

as string)

(3)mapjoin

mapjion會把小表全部讀入記憶體中,在map階段直接拿另外乙個表的資料和記憶體中表資料做匹配,由於在map階段進行了join操作,省去了reduce執行,效率也會高很多。這樣就不會由於資料傾斜導致某個reduce上落資料太多而失敗。

適用條件:關聯操作中有一張表非常小(<1000行)

需要做不等值join操作(a.x < b.y 或者 a.x like b.y等)

例1:關聯操作中有一張表非常小

select f.a, f.b from a t join b f  on ( f.a=t.a and f.ftime=

20110802

) 該語句中b表有30億行記錄,a表只有100行記錄,而且b表中資料傾斜特別嚴重,有乙個key上有15億行記錄,在執行過程中特別的慢,而且在reduece的過程中遇有記憶體不夠而報錯。

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

例2:需要做不等值join操作

select a.a, a.b from a join b where a.a>

b.a將不等條件寫在where中,那麼mapreduce過程中會進行笛卡爾積,執行效率特別低。

改進:select

/*+ mapjoin(a)

*/ a.a, a.b from a join b where a.a>b.a

例3:小表不小不大

select

*from

loga

left

outer

join

users b

on a.user_id

= b.user_id

;users 表有 600w

+ 的記錄,把 users 分發到所有的 map 上也是個不小的開銷,而且 map join 不支援這麼大的小表。如果用普通的 join

,又會碰到資料傾斜的問題。

解決方案:

select

/*+mapjoin(x)*/*

from

loga

left

outer

join

(

select

/*+mapjoin(c)

*/d.*

from ( select

distinct

user_id

from

log) c

join

users d

on c.user_id

= d.user_id

) x

on a.user_id

= b.user_id;

Hive資料傾斜

hive資料傾斜問題 傾斜原因 map輸出資料按key hash分配到reduce中,由於key分布不均勻 或者業務資料本身的特點。等原因造成的reduce上的資料量差異過大。1.1 key分布不均勻 1.2 業務資料本身的特性 1.3 sql語句造成資料傾斜 解決方案 1 引數調節 hive.ma...

hive資料傾斜

key 分布不均勻 業務資料本身的特性 建表考慮不周全 某些 hql 語句本身就存在資料傾斜 1.空值產生的資料傾斜 在日誌中,常會有資訊丟失的問題,比如日誌中的 user id,如果取其中的 user id 和使用者表中的 user id 相關聯,就會碰到資料傾斜的問題。解決方案 1 user i...

hive 資料傾斜介紹

hive在跑資料時經常會出現資料傾斜的情況,使的作業經常reduce完成在99 後一直卡住,最後的 花了幾個小時都沒跑完,這種情況就很可能是資料傾斜的原因,解決方法要根據具體情況來選擇具體的方案 這種情況可以對異常值賦乙個隨機值來分散key 如 selectuserid name fromuser ...