HiveQL中如何排查数据倾斜问题
原文:https://blog.csdn.net/u012151684/article/details/77074356
如果某個key下記錄數遠超其他key,在join或group的時候可能會導致某個reduce任務特別慢。本文分析下join的場景。
本例子SQL如下:查詢每個appid打開的次數,需要排除掉作弊的imei。
說明:表cheat_imei,7500萬條,無大key,為作弊的imei。表imei_open_app,5億6526萬條,為每個imei打開的appid。該表中存在大key,md5imei=54bc0748b1c0fb46135d117b6d26885e的記錄數有2億3659萬條。
Hadoop環境:
Hadoop 2.6.0-cdh5.8.0 ? ? ??hive-1.1.0-cdh5.8.0
會導致的問題
可能會導致下面2個問題
1)某個reduce task,卡在99.9%半天不動。如下
?
2)任務超時被殺掉
Reduce處理的數據量巨大,在做full gc的時候,stop the world。導致響應超時,超出默認的600秒,任務被殺掉。報錯信息
?
AttemptID:attempt_1498075186313_242232_r_000021_1 Timed outafter 600 secs Container killed by the ApplicationMaster. Container killed onrequest. Exit code is 143 Container exited with a non-zero exit code 143。
?
如何判斷是大key導致的問題
可以通過下面方法。
?
4.1 通過時間判斷
如果某個reduce的時間比其他reduce時間長的多。(注意:如果每個reduce執行時間差不多,都特別長,則可能是reduce設置過少導致的)。如下圖。大部分task在4分鐘之內完成,只有r_000021這個task在30分鐘內還沒完成。
?
另外注意,這里面需要排除一種特殊情況。有時候,某個task執行的節點可能有問題,導致任務跑的特別慢。這個時候,mapreduce的推測執行,會重啟一個任務。如果新的任務在很短時間內能完成,通常則是由于task執行節點問題導致的個別task慢。如果推測執行后的task執行任務也特別慢,那更能說明該task可能會有傾斜問題。
?
4.2 通過任務Counter判斷
Counter會記錄整個job以及每個task的統計信息。counter的url一般類似:
http://rm:9099/proxy/application_1498075186313_242232/mapreduce/taskcounters/task_1498075186313_242232_r_000017
?
1)通過輸入記錄數
普通的task counter如下
?
而task=000021的counter如下,其輸入記錄數是2億4000萬。是其他任務的10幾倍
?
2)通過輸出字符數
普通的task counter如下,
?
而task=000021的counter如下,是其他任務的幾十倍
?
如何找到大key及對應SQL執行代碼
5.1 找到對應大key
一般情況下,hive在做join的時候,會打印join的日志。我們通過日志查找大key。
?
1)找到任務特別慢的那個task,打開對應日志,url類似于
http://rm:8042/node/containerlogs/container_e115_1498075186313_242232_01_000416/hdp-ads-audit/syslog/?start=0
?
2)搜索日志中出現的“rows for joinkey”,如下圖。
?
3) 找到時間跨度最大的那條記錄,如下圖。
比如[54bc0748b1c0fb46135d117b6d26885e],處理的時間從2017-08-03 11:31:30 一直到2017-08-03 11:46:35,耗時15分鐘,任務依然沒有結束。
?
。。。。。。由于日志過長,中間部分省略。。。。。。。
?
另外,從日志中也可能看到,54bc0748b1c0fb46135d117b6d26885e已經處理了236528000條數據,實際情況該key在imei_open_app中確實有2億3659萬條數據。
?
5.2 確定任務卡住的stage
?
1)通過jobname確定stage
一般通過Hive的默認jobname會帶上名稱會帶上stage階段,如下為Stage-1。
?
?
2)如果jobname是自定義的,那可能沒法通過jobname判斷stage。需要借助于任務日志。
?
找到執行特別慢的那個task,搜索 “CommonJoinOperator: JOIN struct” 。Hive在做join的時候,會把join的key打印到日志中。如下。
?
上圖中的關鍵信息是struct<_col1:string,_col6:string>
這時候,需要參考該SQL的執行計劃。通過參考執行計劃,可以斷定該階段為stage1階段。
?
這時候,需要參考該SQL的執行計劃。通過參考執行計劃,可以斷定該階段為stage1階段。
?
5.3 確定SQL執行代碼
確定了執行階段,即stage。通過執行計劃,則可以判斷出是執行哪段代碼時出現了傾斜。還是從上圖,可以推測出是在執行下面紅框中代碼時出現了數據傾斜。
?
解決方案
6.1 過濾掉臟數據
如果大key是無意義的臟數據,直接過濾掉。本場景中大key無實際意義,為非常臟數據,直接過濾掉。
6.2 數據預處理
數據做一下預處理,盡量保證join的時候,同一個key對應的記錄不要有太多。
6.3 增加reduce個數
如果數據中出現了多個大key,增加reduce個數,可以讓這些大key落到同一個reduce的概率小很多。
6.4 轉換為mapjoin
如果兩個表join的時候,一個表為小表,可以用mapjoin做。
6.5 大key單獨處理
將大key和其他key分開處理,sql如下
?
?
6.6 hive.optimize.skewjoin
會將一個join?sql 分為兩個job。另外可以同時設置下hive.skewjoin.key,默認為10000。參考:
https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties
參數對full outer join無效。
6.7 調整內存設置
適用于那些由于內存超限內務被kill掉的場景。通過加大內存起碼能讓任務跑起來,不至于被殺掉。該參數不一定會明顯降低任務執行時間。
如:
setmapreduce.reduce.memory.mb=5120 ;
setmapreduce.reduce.java.opts=-Xmx5000M?-XX:MaxPermSize=128m ;
總結
以上是生活随笔為你收集整理的HiveQL中如何排查数据倾斜问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1031 Hello World for
- 下一篇: JMS学习六(ActiveMQ消息传送模