The important thing in life is to have a great aim , and the determination

          常用鏈接

          統(tǒng)計

          IT技術(shù)鏈接

          保險相關(guān)

          友情鏈接

          基金知識

          生活相關(guān)

          最新評論

          hive大數(shù)據(jù)傾斜總結(jié)

          在做Shuffle階段的優(yōu)化過程中,遇到了數(shù)據(jù)傾斜的問題,造成了對一些情況下優(yōu)化效果不明顯。主要是因為在Job完成后的所得到的Counters是整個Job的總和,優(yōu)化是基于這些Counters得出的平均值,而由于數(shù)據(jù)傾斜的原因造成map處理數(shù)據(jù)量的差異過大,使得這些平均值能代表的價值降低。Hive的執(zhí)行是分階段的,map處理數(shù)據(jù)量的差異取決于上一個stage的reduce輸出,所以如何將數(shù)據(jù)均勻的分配到各個reduce中,就是解決數(shù)據(jù)傾斜的根本所在。規(guī)避錯誤來更好的運行比解決錯誤更高效。在查看了一些資料后,總結(jié)如下。

          1數(shù)據(jù)傾斜的原因

          1.1操作:

          關(guān)鍵詞

          情形

          后果

          Join

          其中一個表較小,

          但是key集中

          分發(fā)到某一個或幾個Reduce上的數(shù)據(jù)遠高于平均值

          大表與大表,但是分桶的判斷字段0值或空值過多

          這些空值都由一個reduce處理,灰常慢

          group by

          group by 維度過小,

          某值的數(shù)量過多

          處理某值的reduce灰常耗時

          Count Distinct

          某特殊值過多

          處理此特殊值的reduce耗時

          1.2原因:

          1)、key分布不均勻

          2)、業(yè)務(wù)數(shù)據(jù)本身的特性

          3)、建表時考慮不周

          4)、某些SQL語句本身就有數(shù)據(jù)傾斜

           

          1.3表現(xiàn):

          任務(wù)進度長時間維持在99%(或100%),查看任務(wù)監(jiān)控頁面,發(fā)現(xiàn)只有少量(1個或幾個)reduce子任務(wù)未完成。因為其處理的數(shù)據(jù)量和其他reduce差異過大。

          單一reduce的記錄數(shù)與平均記錄數(shù)差異過大,通常可能達到3倍甚至更多。 最長時長遠大于平均時長。

           

          2數(shù)據(jù)傾斜的解決方案

          2.1參數(shù)調(diào)節(jié):

          hive.map.aggr=true

          Map 端部分聚合,相當于Combiner

          hive.groupby.skewindata=true

          有數(shù)據(jù)傾斜的時候進行負載均衡,當選項設(shè)定為 true,生成的查詢計劃會有兩個 MR Job。第一個 MR Job 中,Map 的輸出結(jié)果集合會隨機分布到 Reduce 中,每個 Reduce 做部分聚合操作,并輸出結(jié)果,這樣處理的結(jié)果是相同的 Group By Key 有可能被分發(fā)到不同的 Reduce 中,從而達到負載均衡的目的;第二個 MR Job 再根據(jù)預(yù)處理的數(shù)據(jù)結(jié)果按照 Group By Key 分布到 Reduce 中(這個過程可以保證相同的 Group By Key 被分布到同一個 Reduce 中),最后完成最終的聚合操作。

           

          2.2 SQL語句調(diào)節(jié):

          如何Join

          關(guān)于驅(qū)動表的選取,選用join key分布最均勻的表作為驅(qū)動表

          做好列裁剪和filter操作,以達到兩表做join的時候,數(shù)據(jù)量相對變小的效果。

          大小表Join

          使用map join讓小的維度表(1000條以下的記錄條數(shù)) 先進內(nèi)存。在map端完成reduce.

          大表Join大表:

          把空值的key變成一個字符串加上隨機數(shù),把傾斜的數(shù)據(jù)分到不同的reduce上,由于null值關(guān)聯(lián)不上,處理后并不影響最終結(jié)果。

          count distinct大量相同特殊值

          count distinct時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最后結(jié)果中加1。如果還有其他計算,需要進行g(shù)roup by,可以先將值為空的記錄單獨處理,再和其他計算結(jié)果進行union。

          group by維度過小:

          采用sum() group by的方式來替換count(distinct)完成計算。

          特殊情況特殊處理:

          在業(yè)務(wù)邏輯優(yōu)化效果的不大情況下,有些時候是可以將傾斜的數(shù)據(jù)單獨拿出來處理。最后union回去。

           

          3典型的業(yè)務(wù)場景

          3.1空值產(chǎn)生的數(shù)據(jù)傾斜

          場景:如日志中,常會有信息丟失的問題,比如日志中的 user_id,如果取其中的 user_id 和 用戶表中的user_id 關(guān)聯(lián),會碰到數(shù)據(jù)傾斜的問題。

          解決方法1 user_id為空的不參與關(guān)聯(lián)(紅色字體為修改后)

          復(fù)制代碼
          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;
          復(fù)制代碼

           

          解決方法賦與空值分新的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;

           

          結(jié)論:方法2比方法1效率更好,不但io少了,而且作業(yè)數(shù)也少了。解決方法1中 log讀取兩次,jobs是2。解決方法2 job數(shù)是1 。這個優(yōu)化適合無效 id (比如 -99 , ’’, null 等) 產(chǎn)生的傾斜問題。把空值的 key 變成一個字符串加上隨機數(shù),就能把傾斜的數(shù)據(jù)分到不同的reduce上 ,解決數(shù)據(jù)傾斜問題。

           

          3.2不同數(shù)據(jù)類型關(guān)聯(lián)產(chǎn)生數(shù)據(jù)傾斜

          場景:用戶表中user_id字段為int,log表中user_id字段既有string類型也有int類型。當按照user_id進行兩個表的Join操作時,默認的Hash操作會按int型的id來進行分配,這樣會導(dǎo)致所有string類型id的記錄都分配到一個Reducer中。

          解決方法:把數(shù)字類型轉(zhuǎn)換成字符串類型

          select * from users a   left outer join logs b   on a.usr_id = cast(b.user_id as string)

           

          3.3小表不小不大,怎么用 map join 解決傾斜問題

          使用 map join 解決小表(記錄數(shù)少)關(guān)聯(lián)大表的數(shù)據(jù)傾斜問題,這個方法使用的頻率非常高,但如果小表很大,大到map join會出現(xiàn)bug或異常,這時就需要特別的處理。 以下例子:

          select * from log a   left outer join users b   on a.user_id = b.user_id;

           

          users 表有 600w+ 的記錄,把 users 分發(fā)到所有的 map 上也是個不小的開銷,而且 map join 不支持這么大的小表。如果用普通的 join,又會碰到數(shù)據(jù)傾斜的問題。

          解決方法:

          select /*+mapjoin(x)*/* from log a   
          left outer join (
          select /*+mapjoin(c)*/d.* from (
          select distinct user_id from log ) c join users d
          on c.user_id = d.user_id ) x
          on a.user_id = b.user_id;

          假如,log里user_id有上百萬個,這就又回到原來map join問題。所幸,每日的會員uv不會太多,有交易的會員不會太多,有點擊的會員不會太多,有傭金的會員不會太多等等。所以這個方法能解決很多場景下的數(shù)據(jù)傾斜問題。

          4總結(jié)

          使map的輸出數(shù)據(jù)更均勻的分布到reduce中去,是我們的最終目標。由于Hash算法的局限性,按key Hash會或多或少的造成數(shù)據(jù)傾斜。大量經(jīng)驗表明數(shù)據(jù)傾斜的原因是人為的建表疏忽或業(yè)務(wù)邏輯可以規(guī)避的。在此給出較為通用的步驟:

          1、采樣log表,哪些user_id比較傾斜,得到一個結(jié)果表tmp1。由于對計算框架來說,所有的數(shù)據(jù)過來,他都是不知道數(shù)據(jù)分布情況的,所以采樣是并不可少的。

          2、數(shù)據(jù)的分布符合社會學統(tǒng)計規(guī)則,貧富不均。傾斜的key不會太多,就像一個社會的富人不多,奇特的人不多一樣。所以tmp1記錄數(shù)會很少。把tmp1和users做map join生成tmp2,把tmp2讀到distribute file cache。這是一個map過程。

          3、map讀入users和log,假如記錄來自log,則檢查user_id是否在tmp2里,如果是,輸出到本地文件a,否則生成<user_id,value>的key,value對,假如記錄來自member,生成<user_id,value>的key,value對,進入reduce階段。

          4、最終把a文件,把Stage3 reduce階段輸出的文件合并起寫到hdfs。

           

          如果確認業(yè)務(wù)需要這樣傾斜的邏輯,考慮以下的優(yōu)化方案:

          1、對于join,在判斷小表不大于1G的情況下,使用map join

          2、對于group by或distinct,設(shè)定 hive.groupby.skewindata=true

          3、盡量使用上述的SQL語句調(diào)節(jié)進行優(yōu)化

          posted on 2017-07-31 19:57 鴻雁 閱讀(194) 評論(0)  編輯  收藏 所屬分類: IT技術(shù)相關(guān)

          主站蜘蛛池模板: 普定县| 淮滨县| 屯留县| 张家川| 客服| 油尖旺区| 梁山县| 青河县| 桐梓县| 保靖县| 梁平县| 霍城县| 隆林| 汉阴县| 肃南| 连云港市| 尉氏县| 赣州市| 永安市| 三门县| 临邑县| 平原县| 河东区| 萨迦县| 南昌县| 辽宁省| 鹤庆县| 烟台市| 格尔木市| 巴里| 昭通市| 光泽县| 札达县| 长宁区| 兴仁县| 湘西| 调兵山市| 荣昌县| 安宁市| 买车| 南开区|