HIVE 数据倾斜浅谈
HIVE 數據傾斜淺談
一、數據傾斜現象
??map100%,reduce一直卡在一個值,如99%。
二、數據傾斜的原因
??數據按key的hash值分配到reduce中,如果有的key值比較集中,就會導致某個或某些reduce分配的數據量太大,這樣當其他reduce運行完畢,分配數據量過大的reduce仍在運行,導致reduce進度一直卡著不動,這種現象被稱為數據傾斜。造成數據傾斜的根本原因就是key值分布不均勻。
三、數據傾斜的操作
join、group by、Count Distinct
四、數據傾斜的處理方法
1. 參數配置方案
1.groupby、count distinct數據傾斜:
hive.map.aggr = true hive.groupby.skewindata=true??有數據傾斜的時候進行負載均衡,當選項設定為 true,生成的查詢計劃會有兩個 MR Job。第一個 MR Job 中,Map 的輸出結果集合會隨機分布到 Reduce 中,每個 Reduce 做部分聚合操作,并輸出結果,這樣處理的結果是相同的 Key 有可能被分發到不同的 Reduce 中,從而達到負載均衡的目的;第二個 MR Job 再根據預處理的數據結果按照 Key 分布到 Reduce 中(這個過程可以保證相同的 Key 被分布到同一個 Reduce 中),最后完成最終的聚合操作。
2.join 的數據傾斜:
??如果join過程中出現了數據傾斜,應該設置為true
set hive.skewjoin.key=100000;??這個是join的鍵對應的記錄條數超過這個值則會進行優化,優化措施:正常是只有一個job的,優化后會有兩個job。當傾斜Key值達到100000以上的時候,hive會把不傾斜的key進行join,傾斜的 key 的數據將會被寫入HDFS臨時文件,hive會再啟動一個job,然后將傾斜的數據進行map 端join,最終將兩個結果合并。
??但是這種處理方式不是所有地方都有效。
2. sql優化方案
1. count distinct、group by
- 當group by key為空時,如果只是計算count
distinct,可以不用處理,直接過濾,在最后結果中加1。如果還有其他計算,需要進行group
by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。 - count(distinct user_id),采用
來替換count(distinct)完成計算。
- 在業務邏輯優化效果的不大情況下,有些時候是可以將傾斜的數據單獨拿出來處理。最后union回去。
2. 空值產生的數據傾斜
1.把空值單獨處理,再與其他值的處理結果進行uinon all.
2.把空值的key變為隨機數。
??方法2比方法1效率更好,不但io少了,而且作業數也少了。解決方法1中 log讀取兩次,jobs是2。解決方法2 job數是1 。這個優化適合無效 id (比如 -99 , ’’, null 等) 產生的傾斜問題。把空值的 key 變成一個字符串加上隨機數,就能把傾斜的數據分到不同的reduce上 ,解決數據傾斜問題。
3. 條件中等號兩端數據類型不同
??類型轉換過程中可能會出現轉換失敗,比較常見的是string轉int,失敗后會造成大量null值,進而流入同一個reduce,導致數據傾斜。
??處理辦法就是在條件中進行類型轉換,保證兩端數據類型一致。
4.小表關聯大表
??Map端join會使所有的 maptask 節點都裝載小表 b 的所有數據,然后大表 a 的 一個數據塊數據比如說是 a1 去跟 b 全量數據做鏈接。實現方法:
select /* +mapjoin(a) */ a.id aid, name, age from a join b on a.id = b.id;??在 hive0.11 版本以后會自動開啟 map join 優化,由兩個參數控制:
set hive.auto.convert.join=true; //設置 MapJoin 優化自動開啟 set hive.mapjoin.smalltable.filesize=25000000 //設置小表不超過多大時開啟 mapjoin 優化5.小表不小關聯大表——處理大表文件,使其變為可加載到內存的小表
??可以根據業務邏輯,只取必要數據(行、列兩個維度限制),盡量減小數據大小,使之成為小表。比如:
當分析某段時間的日志表logs數據是億級的,用戶表users數目有數十萬,把users當小表做map join會超出內存時,我們可以把users行數減少到只取出logs中包含的users,然后進行列裁剪,這樣可能大大縮減users所占空間,從而可以實現map join。
6.大表關聯大表
??兩個Hive表進行join的時候,如果數據量都比較大,那么此時可以看一下兩個Hive表中的key分布情況。
6.1 如果出現數據傾斜,是因為其中某一個Hive表中的少數幾個key的數據量過大,而另一個Hive表中的所有key都分布比較均勻
方案實現思路:
- 對包含少數幾個數據量過大的key的那個表,通過sample算子采樣出一份樣本來,然后統計一下每個key的數量,計算出來數據量最大的是哪幾個key。
- 然后將這幾個key對應的數據從原來的表中拆分出來,形成一個單獨的表,并給每個key都打上n以內的隨機數作為前綴;
- 接著將另一個表,也過濾出來這幾個key對應的數據并形成一個單獨的表,將每條數據膨脹成n條數據,這n條數據都按順序附加一個0~n的前綴。
- 再將附加了隨機前綴的獨立表與另一個膨脹n倍的獨立表進行join,此時就可以將原先相同的key打散成n份,分散到多個task中去進行join了。
- 不傾斜的數據照常join即可。
- 最后將兩個join的結果使用union all算子合并起來即是最終結果。
- 比較集中的key值如果不想做數據膨脹,也可以使用map join將記錄較少的表加載到內存中。
方案優點:對于join導致的數據傾斜,如果只是某幾個key導致了傾斜,采用該方式可以用最有效的方式打散key進行join。而且只需要針對少數傾斜key對應的數據進行擴容n倍,不需要對全量數據進行擴容。避免了占用過多內存。
方案缺點:如果導致傾斜的key特別多的話,比如成千上萬個key都導致數據傾斜,那么這種方式也不適合。
方案二:分桶join+map join
參見:https://blog.csdn.net/Samaritan_H/article/details/79090103
6.2 如果出現數據傾斜的key比較多
方案一:我們可以按6.1的方式對傾斜表所有數據加上n以隨機前綴,對另一張表進行全表數據膨脹操作,然后進行關聯。
這樣可以緩解數據傾斜問題。但是比較消耗內存資源。
方案二:依舊分離出比較集中的key值記錄,另一張表也取出相應的key值記錄,然后開啟map join進行關聯操作,對結果進行uion。
方案三:分桶join+map join
參考文獻:https://blog.csdn.net/jin6872115/article/details/79878391
總結
以上是生活随笔為你收集整理的HIVE 数据倾斜浅谈的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle数据库read only,o
- 下一篇: java setter_java – 如