如何解決Hive中經常出現的資料傾斜問題
Hive 執行 MapReduce 過程中經常會出現資料傾斜問題,具體表現為:作業經常在 Reduce 過程完成
99% 的時候一直停留,最後
1%
一直保持很久才完成。這種情況是由於:在資料量很大的情況下,在 MapReduce 的 Shuffle 過程執行後,key值分佈到
Reducer 節點不均勻;有的 key 少,雜湊後被分在不同節點中沒有問題,但是有的 key 特別的多,過於集中了,全被分配在一個
Reducer 節點,所以其他的 Reducer 都執行完了都在等這個量大的 key
值,這就導致了資料傾斜。通俗的話來講就是,一堆幹完活的人等那個乾的最慢的人,不是因為那個人能力差,大家能力水平都相同,是他真的幹不完……被分配太多了,別人做完了也沒法幫忙。
所以這也違背了 MapReduce 方法論產生的核心思路,不怕活兒多,活多我們們可以多分配人手;最怕的就是活分配不均勻,有人乾的多,有人乾的少,出現時間上的浪費。這些工作在 MapReduce 過程中,往往都出現在
GROUP
BY
等分組,各種型別
JOIN
過程中。常見產生資料傾斜的原因大致有以下幾種:
- 大量空值
- 某個 key 值大量重複
- 不同資料型別關聯
- COUNT(DISTINCT)
接下來詳細介紹各種出現以及如何避免這類問題的出現。
二、問題分類及解決思路
1.大量空值產生資料傾斜
解決思路:利用隨機數將空值進行隨機填充,注意:不要讓隨機數碰撞到其他值,提前要測試下是否有膨脹現象發生,之所以選擇以下例子是因為流量表中往往存在無”主鍵”的情況,c端使用者不登入,就不會在流量表記錄使用者唯一值。例如:
最佳化前:
select * from click_log a left join users b on a.user_id = b.user_id;
最佳化方法1. 讓 user_id 為空的不參與關聯,
select *
from click_log a
join users b
on a.user_id is not null
and a.user_id = b.user_id
union all
select * from click_log a where a.user_id is null;
最佳化方法2. 讓隨機數衝散堆積在一個人 Reduce 中的很多 null 值,
select *
from click_log a
left join users b
on case
when a.user_id is null then
concat('dp_hive', rand())
else
a.user_id
end = b.user_id;
2.某 key 值大量重複產生資料傾斜解釋:如果key均為空值,大量的key會分佈在同一個Reduce節點上;在其他Reduce節點完成ReduceTask後,存在大量空值的Reduce還未完成Task,因此產生資料傾斜。
concat('dp_hive',rand())
是為了把空值變成一個字串加上隨機數的,把
null
值傾斜的資料分佈在不同Reduce節點上,間接把傾斜的資料分佈在不同Reduce上。
其實,當key值非空,但某個key出現大量重複的情況的解決方案和上述空值情況相同,均為引入隨機數進行最佳化。
最佳化前:
select a.key as key, count(b.pv) as pv
from test_table1 a
inner join test_table2 b
on a.key = b.key
group by 1;
最佳化後:
select a.key as key, b.pv as pv
from (select key from test_table1) a
inner join (select key, sum(pv) as pv
from (select key, round(rand() * 1000) as rnd, count(1) as pv
from test_table2
group by 1, 2) tmpgroup by 1) b
on a.key = b.key;
解釋:
round(rand()*1000) as rnd
–>
sum(pv)
加入隨機,將本來ReduceTask在一組的key,拆分成多組進行處理,增加併發度。
3.不同資料型別關聯產生資料傾斜
使用者表user_id欄位為
bigint,click_log
表中user_id欄位既有string型別也有bigint型別。當按照user_id進行兩個表的join操作時,預設的hash操作會按bigint型的id來進行分配,這樣會導致所有string型別id的記錄都分配到一個Reduce中,例如:
最佳化前:
select * from click_log a left join users b on a.user_id = b.user_id;
最佳化後:
select *
from users a
left join click_log b
on a.user_id = cast(b.user_id as string)
4.COUNT(DISTINCT) 產生資料傾斜
首先,說說
group by
和
distinct
的區別。我在工作過程中實踐過很多場景,發現在處理時間上並沒有什麼本質區別,都是在一個 job 中,出現一個 reduce 過程。那麼為什麼一定要要強呼叫
group by
代替
distinct
呢? 我在網上搜了很多資料,都沒有說清楚這個問題的本質。接下來我來說說我的理解:
其實,大部分情況我們根本不用代替,因為
大部分的情況 資料是不傾斜的。
舉個例子,我們經常計算每個使用者這一年變換手機號次數,Email次數等等,當然不會傾斜,因為誰沒事兒老去更換手機號呢!
所以,資料不傾斜的時候基本上兩個過程是等價的。但是,一旦出現資料傾斜,還是要代替一下,因為
group by
覆蓋到了很多 hive 計算引擎引數設定,例如:
- set hive.groupby.mapaggr.checkinterval = 100000; – 這個是 grby 的鍵對應的記錄條數超過這個值則會進行最佳化
- set hive.groupby.skewindata = true; – 如果 grby 過程中出現傾斜,設定成 true,會自動將相同的reduceKey進行 Hashing
除此之外,
join
也涉及到了一些,如下:
- set hive.skewjoin.key = 100000; – 這是 join 的鍵對應的記錄條數超過這個值則會進行最佳化;
- set hive.optimize.skewjoin = true; – 如果是 join 過程中出現資料傾斜,設定成 true
其次,
count(distinct)
會壓力都積壓在一個 reduce 過程中,導致一個job處理太多資料,導致資料傾斜,改成
count(1)
+
group by
的處理方式,這樣會將整個過程解耦,進而分解整體過程中的壓力。
最後,有一點自己在寫 Hive Sql 時候的體會,程式碼可讀性和效能最佳化,一定都要考慮,過於複雜的程式碼邏輯一定要加註釋,增強程式碼可讀性,舉個例子:
select a, sum(b), count(distinct c),.. . from T group by a;
最佳化後本應該是:
select a, sum(b) as b, count(c) as c,.. .
from (select a, b, null as c,.. .
from T
group by a, b
union all
select a, 0 as b, c,.. . from T group by a, c union all .. .) tmp1
group by a;
其實,企業級的 hive 在處理 T+1 資料時,處理的速度並不會相差太遠,即 最佳化程度不高的情況下,建議保留業務邏輯。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29209863/viewspace-2757366/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Hive資料傾斜Hive
- 實戰 | Hive 資料傾斜問題定位排查及解決Hive
- 如何解決 Redis 資料傾斜、熱點等問題Redis
- IoT資料傾斜如何解決
- 大資料常見問題之資料傾斜大資料
- Hive千億級資料傾斜解決方案Hive
- 【Spark篇】---Spark解決資料傾斜問題Spark
- hive優化-資料傾斜優化Hive優化
- 【Hive】資料傾斜優化 shuffle, join, group byHive優化
- 資料傾斜解決辦法
- Spark 資料傾斜及其解決方案Spark
- Oracle資料傾斜導致的問題-有繫結變數Oracle變數
- Oracle資料傾斜導致的問題-無繫結變數Oracle變數
- Spark學習——資料傾斜Spark
- 換IP經常出現的問題及其解決方案
- 淺析 Hadoop 中的資料傾斜(R0.1)Hadoop
- 一種自平衡解決資料傾斜的分表方法
- 大資料SQL優化之資料傾斜解決案例全集大資料SQL優化
- 如何解決各個行業出現的資料洩露問題?行業
- Redis 切片叢集的資料傾斜分析Redis
- 巧用函式索引解決資料傾斜列查詢函式索引
- 爬蟲中經常出現Traceback (most recent call last):問題解決!!!爬蟲AST
- 解決hive資料庫 插入資料很慢的問題Hive資料庫
- Oracle中利用函式索引處理資料傾斜案例Oracle函式索引
- PostgreSQL DBA(193) - 資料傾斜下的HashJoinSQL
- ORACLE通過BIND_AWARE+SQL PATCH解決SQL繫結變數中資料傾斜的問題OracleSQL變數
- 傾斜攝影三維模型的立體裁剪的問題分析模型
- Spark SQL三種join和資料傾斜的產生和解決辦法SparkSQL
- hadoop 透過cachefile來避免資料傾斜Hadoop
- 好程式設計師Java教程分享Java中經常出現的問題程式設計師Java
- 如何解決大資料安全問題大資料
- 如何解決資料庫配置問題資料庫
- 如何解決Facebook SDK常見問題?
- myeclispe中向mysql中插入中文資料出現??問題解決辦法LispMySql
- 索引資料列傾斜度(skew)問題索引
- 2D開發SpaceShooterGame,飛機移動出現傾斜GAM
- Oracle面對“資料傾斜列使用繫結變數”場景的解決方案Oracle變數
- 如何解決input遇到fixed,absolute佈局出現的問題