HIVE- 數據傾斜


數據傾斜就是由於數據分布不均勻,數據大量集中到一點上,造成數據熱點。大多數情況下,分為一下三種情況:

1.map端執行比較快,reduce執行很慢,因為partition造成的數據傾斜。

2.某些reduce很快,某些reduce很慢,也是因為partition造成的數據傾斜。 

3.某些map執行很快,某些map執行很慢,這是因為數據本身的分布的不合理性造成的。 

造成上面reduce和map任務運行很緩慢本質上就兩種情況:

第一:reduce緩慢是因為partition造成滴; 
第二:map端緩慢是因為數據本身的分布不合理性。

下面介紹map緩慢和reduce緩慢

Reduce端緩慢:兩個table的join操作會造成數據傾斜,會造成reduce緩慢,這個相對比較好解決,我們不是有三種解決join性能的方案嗎?mapjoin,common join,smbJoin可以解決數據傾斜。另外,有些情況下造成的reduce緩慢無法解決,因為數據本身也不是服從均勻分布。大多數還是高斯分布。 
reduce性能本質上是由於groupby操作導致的,而count(distinct)內部本質也是有groupby實現

map端緩慢:這種情況是由於每條數據的相對位置造成的。有兩種方案:

第一:設置在map端聚合,set hive.map.aggr=true 可以減小壓力(默認開啟) 
第二:可以set hive.groupby.skewindata=true(默認關閉),此時hive的執行在MR后台會存在兩個map一個reduce,第一個map本質上就是先對數據進行shuffle,第二個map就可以對shuffle之后的數據進行操作。

join和Group的優化 
2.1 對於普通的join操作,會在map端根據key的hash值,shuffle到某一個reduce上去,在reduce端做join連接操作,內存中緩存join左邊的表,遍歷右邊的表,一次做join操作。所以在做join操作時候,將數據量多的表放在join的右邊。 
當數據量比較大,並且key分布不均勻,大量的key都shuffle到一個reduce上了,就出現了數據的傾斜。 

在map端產生join

         mapJoin的主要意思就是,當鏈接的兩個表是一個比較小的表和一個特別大的表的時候,我們把比較小的table直接放到內存中去,然后再對比較大的表格進行map操作。join就發生在map操作的時候,每當掃描一個大的table中的數據,就要去去查看小表的數據,哪條與之相符,繼而進行連接。這里的join並不會涉及reduce操作。map端join的優勢就是在於沒有shuffle,


2.2 對於Group操作,首先在map端聚合,最后在reduce端坐聚合,hive默認是這樣的,以下是相關的參數 
· hive.map.aggr = true是否在 Map 端進行聚合,默認為 True 
· hive.groupby.mapaggr.checkinterval = 100000在 Map 端進行聚合操作的條目數目

當然有的hive操作,不存在數據傾斜的問題,比如數據聚合類的操作,像sum、count,因為已經在map端做了聚合操作了,到reduce端的數據相對少一些,所以不存在這個問題。

空值數據傾斜

場景:如日志中,常會有信息丟失的問題,比如全網日志中的user_id,如果取其中的user_id和bmw_users關聯,會碰到數據傾斜的問題。

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

Select * From log a

Join bmw_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 bmw_users b 

on case when a.user_id is null then concat(‘dp_hive’,rand() ) else a.user_id end = b.user_id; 

 

結論:方法2比方法效率更好,不但io少了,而且作業數也少了。方法1 log讀取兩次,jobs是2。方法2 job數是1 。這個優化適合無效id(比如-99,’’,null等)產生的傾斜問題。把空值的key變成一個字符串加上隨機數,就能把傾斜的數據分到不同的reduce上 ,解決數據傾斜問題。附上hadoop通用關聯的實現方法(關聯通過二次排序實現的,關聯的列為parition key,關聯的列c1和表的tag組成排序的group key,根據parition key分配reduce。同一reduce內根據group key排序)

 

不同數據類型關聯產生數據傾斜

場景:一張表s8的日志,每個商品一條記錄,要和商品表關聯。但關聯卻碰到傾斜的問題。s8的日志中有字符串商品id,也有數字的商品id,類型是string的,但商品中的數字id是bigint的。猜測問題的原因是把s8的商品id轉成數字id做hash來分配reduce,所以字符串id的s8日志,都到一個reduce上了,解決的方法驗證了這個猜測。

解決方法:把數字類型轉換成字符串類型

Select * from s8_log a

Left outer join r_auction_auctions b

On a.auction_id = cast(b.auction_id as string);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM