在做shuffle階段的優化過程中,遇到了資料傾斜的問題,造成了對一些情況下優化效果不明顯。主要是因為在job完成後的所得到的counters是整個job的總和,優化是基於這些counters得出的平均值,而由於資料傾斜的原因造成map處理資料量的差異過大,使得這些平均值能代表的價值降低。hive的執行是分階段的,map處理資料量的差異取決於上乙個stage的reduce輸出,所以如何將資料均勻的分配到各個reduce中,就是解決資料傾斜的根本所在。規避錯誤來更好的執行比解決錯誤更高效。在檢視了一些資料後,總結如下。
1.2原因:
1)、key分布不均勻
2)、業務資料本身的特性
3)、建表時考慮不周
4)、某些sql語句本身就有資料傾斜
1.3表現:
任務進度長時間維持在99%(或100%),檢視任務監控頁面,發現只有少量(1個或幾個)reduce子任務未完成。因為其處理的資料量和其他reduce差異過大。
單一reduce的記錄數與平均記錄數差異過大,通常可能達到3倍甚至更多。 最長時長遠大於平均時長。
2資料傾斜的解決方案
2.1引數調節:
hive.map.aggr=true
map 端部分聚合,相當於combiner
hive.groupby.skewindata=true
有資料傾斜的時候進行負載均衡,當選項設定為 true,生成的查詢計畫會有兩個 mr job。第乙個 mr job 中,map 的輸出結果集合會隨機分布到 reduce 中,每個 reduce 做部分聚合操作,並輸出結果,這樣處理的結果是相同的 group by key 有可能被分發到不同的 reduce 中,從而達到負載均衡的目的;第二個 mr job 再根據預處理的資料結果按照 group by key 分布到 reduce 中(這個過程可以保證相同的 group by key 被分布到同乙個 reduce 中),最後完成最終的聚合操作。
2.2 sql語句調節:
如何join:
關於驅動表的選取,選用join key分布最均勻的表作為驅動表
做好列裁剪和filter操作,以達到兩表做join的時候,資料量相對變小的效果。
大小表join:
使用map join讓小的維度表(1000條以下的記錄條數) 先進記憶體。在map端完成reduce.
大表join大表:
把空值的key變成乙個字串加上隨機數,把傾斜的資料分到不同的reduce上,由於null值關聯不上,處理後並不影響最終結果。
count distinct大量相同特殊值
count distinct時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最後結果中加1。如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。
group by維度過小:
採用sum() group by的方式來替換count(distinct)完成計算。
特殊情況特殊處理:
在業務邏輯優化效果的不大情況下,有些時候是可以將傾斜的資料單獨拿出來處理。最後union回去。
3典型的業務場景
3.1空值產生的資料傾斜
場景:如日誌中,常會有資訊丟失的問題,比如日誌中的 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;12
3456
7解決方法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;12
34結論:方法2比方法1效率更好,不但io少了,而且作業數也少了。解決方法1中 log讀取兩次,jobs是2。解決方法2 job數是1 。這個優化適合無效 id (比如 -99 , 』』, null 等) 產生的傾斜問題。把空值的 key 變成乙個字串加上隨機數,就能把傾斜的資料分到不同的reduce上 ,解決資料傾斜問題。
3.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)12
33.3小表不小不大,怎麼用 map join 解決傾斜問題
使用 map join 解決小表(記錄數少)關聯大表的資料傾斜問題,這個方法使用的頻率非常高,但如果小表很大,大到map join會出現bug或異常,這時就需要特別的處理。 以下例子:
select * from log a
left outer join users b
on a.user_id = b.user_id;12
3users 表有 600w+ 的記錄,把 users 分發到所有的 map 上也是個不小的開銷,而且 map join 不支援這麼大的小表。如果用普通的 join,又會碰到資料傾斜的問題。
解決方法:
使map的輸出資料更均勻的分布到reduce中去,是我們的最終目標。由於hash演算法的侷限性,按key hash會或多或少的造成資料傾斜。大量經驗表明資料傾斜的原因是人為的建表疏忽或業務邏輯可以規避的。在此給出較為通用的步驟:
1、取樣log表,哪些user_id比較傾斜,得到乙個結果表tmp1。由於對計算框架來說,所有的資料過來,他都是不知道資料分布情況的,所以取樣是並不可少的。
2、資料的分布符合社會學統計規則,貧富不均。傾斜的key不會太多,就像乙個社會的富人不多,奇特的人不多一樣。所以tmp1記錄數會很少。把tmp1和users做map join生成tmp2,把tmp2讀到distribute file cache。這是乙個map過程。
3、map讀入users和log,假如記錄來自log,則檢查user_id是否在tmp2裡,如果是,輸出到本地檔案a,否則生成
Hive調優 資料傾斜
1 通常情況下,作業會通過input的目錄產生乙個或者多個map任務。主要的決定因素有 input的檔案總個數,input的檔案大小,集群設定的檔案塊大小 目前為128m,可在hive中通過set dfs.block.size 命令檢視到,該引數不能自定義修改 2 舉例 a 乙個大檔案 假設inpu...
Hive資料傾斜調優
開發人員首先要確認幾點 需要計算的指標真的需要從資料倉儲的公共明細層來自行彙總嗎?資料團隊開發的公共彙總層是否可以滿足其要求了?真的需要掃瞄這麼多分割槽嗎?能掃瞄一周的就不掃瞄一年的。盡量不要使用select from table這樣的詞語,能指定哪一列就用那一列,盡量新增過濾條件。輸入檔案不要大量...
Hive資料傾斜及解決方案
1.現象 資料傾斜是進行大資料計算時最經常遇到的問題之一。當我們在執行hiveql或者執行mapreduce作業時候,如果遇到一直卡在map100 reduce99 檢視任務監控頁面,發現只有少量 1個或幾個 reduce子任務未完成。因為其處理的資料量和其他reduce差異過大。一般就是遇到了資料...