Hive資料傾斜調優

2022-09-09 06:06:15 字數 3510 閱讀 7816

開發人員首先要確認幾點:

需要計算的指標真的需要從資料倉儲的公共明細層來自行彙總嗎?資料團隊開發的公共彙總層是否可以滿足其要求了?

真的需要掃瞄這麼多分割槽嗎?能掃瞄一周的就不掃瞄一年的。

盡量不要使用select * from table這樣的詞語,能指定哪一列就用那一列,盡量新增過濾條件。

輸入檔案不要大量小檔案,小檔案可以先合併成大檔案。

如果以上問題都排完雷了,資料傾斜問題依然存在,那我們繼續往下看~

情形

後果

join

其中乙個表較小,

但是key集中

分發到某乙個或幾個reduce上的資料遠高於平均值

大表與大表,但是分桶的判斷欄位0值或空值過多

這些空值都由乙個reduce處理,灰常慢

group by

group by 維度過小,

某值的數量過多

處理某值的reduce灰常耗時

count distinct

某特殊值過多

處理此特殊值的reduce耗時

key分布不均勻

業務資料本身的特性

建表時考慮不周

某些sql語句本身就有資料傾斜

任務進度長時間維持在99%(或100%),檢視任務監控頁面,發現只有少量(1個或幾個)reduce子任務未完成。因為其處理的資料量和其他reduce差異過大。

單一reduce的記錄數與平均記錄數差異過大,通常可能達到3倍甚至更多。 最長時長遠大於平均時長。

舉例:比如按照經銷商的**商來做group by,那麼有些大經銷商就有很多訂單,而一些小經銷商只有幾個訂單,那麼分配給發大經銷商的reduce task就有許多訂單,所以造成資料傾斜。

解決:引數設定

hive.map.aggr = true

hive.groupby.skewindata=true

在開發過程中,要小心使用count distinct。

舉例:

select count(distinct user) from table

解決:sql優化

由於必須要去重了,所以hive會把所有的map階段輸出都放在乙個reduce上,造成效能問題,所以通過group by再count進行優化。

select count(*)from(  select user  from table  group by user) tmp

舉例:有兩個表,乙個是**商,乙個是訂單,**商的表不會很大,因為**商就這麼點兒人,而訂單的表就很大了。兩個表join一下,就是乙個很經典的大表join小表問題。

解決:mapjoin hint的方式

select /*

+mapjoin(b小表)

*/

舉例:有兩個表,a表表示買家賣家的交易彙總表,b表表示賣家的段位評級。想要獲得賣家在各個級別賣家的成交比例。

如某個買家:金冠店:40%,皇冠店:30%,鑽石店:20%,星級店:10%

這兩個表都會很大,超過mapjoin1g的限制,所以需要找其他方法解決。

如果大表和大表進行join操作,則可採用skewjoin

skewjoin原理

對於skewjoin.key,在執行job時,將它們存入臨時的hdfs目錄。其它資料正常執行

對傾斜資料開啟map join操作,對非傾斜值採取普通join操作

將傾斜資料集和非傾斜資料及進行合併操作

該引數為在執行時動態指定資料進行skewjoin,一般和hive.skewjoin.key引數一起使用

set hive.optimize.skewjoin=true

; set hive.skewjoin.key=100000;

以上引數表示當記錄條數超過100000時採用skewjoin操作

此思路有兩種途徑:限制行和列

限制行的思路是比如不需要join b表全部,只需要join a表中存在的就行,比如過濾掉90天內沒交易過的賣家

限制列的思路是只取需要的字段

解決場景是傾斜的值明確且數量很少,如用null引起的值。

核心是將這些傾斜的值發放到隨機的reduce,具體做法是在join時對這些特殊的值concat隨機數,從而達到隨即分發的目的。

on (case when a.user_id is null then concat('hive',rand()) else a.user_id end) = b.user_id

最徹底的方式就是動態一分為二,將傾斜和不傾斜的值分開處理,如果不傾斜的直接正常join,如果傾斜的找出來做mapjoin,最後結果union all即可。

場景:如日誌中,常會有資訊丟失的問題,比如日誌中的 user_id,如果取其中的 user_id 和 使用者表中的user_id 關聯,會碰到資料傾斜的問題。

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

select *from log a

join users b

on a.user_id is not

null

and a.user_id =b.user_id

union all

select *from log a

where a.user_id is

null;

解決方法2 :賦與空值分新的key值

select *from log a

left outer join users b on

case when a.user_id is null 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上 ,解決資料傾斜問題。

場景:使用者表中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)

Hive調優 資料傾斜

1 通常情況下,作業會通過input的目錄產生乙個或者多個map任務。主要的決定因素有 input的檔案總個數,input的檔案大小,集群設定的檔案塊大小 目前為128m,可在hive中通過set dfs.block.size 命令檢視到,該引數不能自定義修改 2 舉例 a 乙個大檔案 假設inpu...

hive的調優以及資料傾斜

調優 fectch抓取 select,filter,limit 這個適合老版本,因為老版本hive預設是minimal,現在新版本都是預設more hive set hive.fetch.task.conversion none 轉為mr hive select from emp query id ...

Hive 資料傾斜解決方案(調優)

在做shuffle階段的優化過程中,遇到了資料傾斜的問題,造成了對一些情況下優化效果不明顯。主要是因為在job完成後的所得到的counters是整個job的總和,優化是基於這些counters得出的平均值,而由於資料傾斜的原因造成map處理資料量的差異過大,使得這些平均值能代表的價值降低。hive的...