HIVE的資料傾斜

2022-09-06 19:03:09 字數 3674 閱讀 7984

由於資料分布不均勻,造成資料大量的集中到一點,造成資料熱點

回到頂部

a、不怕資料大,怕資料傾斜

b、jobs 數比較多的作業執行效率相對比較低,如子查詢比較多

c、 sum,count,max,min 等聚集函式,通常不會有資料傾斜問題

回到頂部

任務進度長時間維持在 99%或者 100%的附近,檢視任務監控頁面,發現只有少量 reduce 子任務未完成,因為其處理的資料量和其他的 reduce 差異過大。 單一 reduce 處理的記錄數和平均記錄數相差太大,通常達到好幾倍之多,最長時間遠大 於平均時長。

回到頂部

a、group by 不和聚集函式搭配使用的時候

b、count(distinct),在資料量大的情況下,容易資料傾斜,因為 count(distinct)是按 group by 字段分組,按 distinct 字段排序

c、 小表關聯超大表 join

回到頂部

a:key 分布不均勻

b:業務資料本身的特性

c:建表考慮不周全

d:某些 hql 語句本身就存在資料傾斜

回到頂部

場景說明

在日誌中,常會有資訊丟失的問題,比如日誌中的 user_id,如果取其中的 user_id 和使用者表中的 user_id 相關聯,就會碰到資料傾斜的問題。

解決方案

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

select * from log a join user b on a.user_id is not null and a.user_id = b.user_id

union all

select * from log c where c.user_id is null;

解決方案 2:賦予空值新的 key 值

select * from log a left outer join user b on

case when a.user_id is null then concat('hive',rand()) else a.user_id end = b.user_id

總結方法 2 比方法 1 效率更好,不但 io 少了,而且作業數也少了,方案 1 中,log 表 讀了兩次,jobs 肯定是 2,而方案 2 是 1。這個優化適合無效 id(比如-99,』』,null)產 生的資料傾斜,把空值的 key 變成乙個字串加上乙個隨機數,就能把造成資料傾斜的 資料分到不同的 reduce 上解決資料傾斜的問題。

改變之處:使本身為 null 的所有記錄不會擁擠在同乙個 reducetask 了,會由於有替代的 隨機字串值,而分散到了多個 reducetask 中了,由於 null 值關聯不上,處理後並不影響最終結果。

場景說明

使用者表中 user_id 欄位為 int,log 表中 user_id 為既有 string 也有 int 的型別, 當按照兩個表的 user_id 進行 join 操作的時候,預設的 hash 操作會按照 int 型別的 id 進 行分配,這樣就會導致所有的 string 型別的 id 就被分到同乙個 reducer 當中

解決方案

把數字型別 id 轉換成 string 型別的 id

select * from user a left outer join log b on b.user_id = cast(a.user_id as string)
注意:使用map join解決小表關聯大表造成的資料傾斜問題。這個方法使用的頻率很高。

map join 概念:將其中做連線的小表(全量資料)分發到所有 maptask 端進行 join,從 而避免了 reducetask,前提要求是記憶體足以裝下該全量資料

以大表 a 和小表 b 為例,所有的 maptask 節點都裝載小表 b 的所有資料,然後大表 a 的 乙個資料塊資料比如說是 a1 去跟 b 全量資料做鏈結,就省去了 reduce 做彙總的過程。 所以相對來說,在記憶體允許的條件下使用 map join 比直接使用 mapreduce 效率還高些, 當然這只限於做 join 查詢的時候。

在 hive 中,直接提供了能夠在 hql 語句指定該次查詢使用 map join,map join 的用法是 在查詢/子查詢的select關鍵字後面新增/*+ mapjoin(tablelist) */提示優化器轉化為map join(早期的 hive 版本的優化器是不能自動優化 map join 的)。其中 tablelist 可以是乙個 表,或以逗號連線的表的列表。tablelist 中的表將會讀入記憶體,通常應該是將小表寫在 這裡。

mapjoin 具體用法:

select /* +mapjoin(a) */ a.id aid, name, age from a join b on a.id = b.id;

select /* +mapjoin(movies) */ a.title, b.rating from movies a join ratings b on a.movieid =

b.movieid;

在 hive0.11 版本以後會自動開啟 map join 優化,由兩個引數控制:

set hive.auto.convert.join=true; //設定 mapjoin 優化自動開啟set hive.mapjoin.smalltable.filesize=25000000 //設定小表不超過多大時開啟 mapjoin 優化

如果是大大表關聯呢?那就大事化小,小事化了。把大表切分成小表,然後分別 map join那麼如果小表不大不小,那該如何處理呢???

使用 map join 解決小表(記錄數少)關聯大表的資料傾斜問題,這個方法使用的頻率非常 高,但如果小表很大,大到 map join 會出現 bug 或異常,這時就需要特別的處理

select * from log a left outer join users b on a.user_id = b.user_id;
users 表有 600w+的記錄,把 users 分發到所有的 map 上也是個不小的開銷,而且 map join 不支援這麼大的小表。如果用普通的 join,又會碰到資料傾斜的問題。

改進方案:

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

) xon a.user_id = x.user_id;

假如,log 裡 user_id 有上百萬個,這就又回到原來 map join 問題。所幸,每日的會員 uv 不會太多,有交易的會員不會太多,有點選的會員不會太多,有佣金的會員不會太多等 等。所以這個方法能解決很多場景下的資料傾斜問題

Hive資料傾斜

hive資料傾斜問題 傾斜原因 map輸出資料按key hash分配到reduce中,由於key分布不均勻 或者業務資料本身的特點。等原因造成的reduce上的資料量差異過大。1.1 key分布不均勻 1.2 業務資料本身的特性 1.3 sql語句造成資料傾斜 解決方案 1 引數調節 hive.ma...

HIVE 資料傾斜

解決資料傾斜,歸根結底是使map的輸出資料更均勻的分布到reduce中去。1 join 1 其中乙個表較小,但是key集中。分發到某乙個或幾個reduce上的資料遠高於平均值 2 大表與大表,但是分桶的判斷欄位0值或空值過多。這些空值都由乙個reduce處理,非常慢 2 group by group...

hive資料傾斜

key 分布不均勻 業務資料本身的特性 建表考慮不周全 某些 hql 語句本身就存在資料傾斜 1.空值產生的資料傾斜 在日誌中,常會有資訊丟失的問題,比如日誌中的 user id,如果取其中的 user id 和使用者表中的 user id 相關聯,就會碰到資料傾斜的問題。解決方案 1 user i...