061 hive中的三種join與數據傾斜


一:hive中的三種join

1.map join

  應用場景:小表join大表

    一:設置mapjoin的方式:

    )如果有一張表是小表,小表將自動執行map join。

      默認是true。

      <property>

        <name>hive.auto.convert.join</name>
        <value>true</value>
      </property>

    )判斷小表

      <property>

        <name>hive.mapjoin.smalltable.filesize</name>
        <value>25000000</value>
      </property>

    二:隱式執行

      /*+ MAPJOIN(tb_name) */

  兩種方式說明:

    

 

2.reduce join

  應用場景:大表join大表

  但是效率不高。

 

3.SMB join(sort merger bucket):hash取余

  排序合並桶。

  條件:A桶個數必須與B桶的個數相同,或者B桶的個數是A桶的個數的倍數

  例如:

    A:4

    B:8

    ——》A的每一個桶joinB桶的兩個小桶就可以了。

  設置:

    hive.auto.convert.sortmerge.join=true

 

二:數據傾斜

1.原因

  指在mapreduce中某一個值數據量過多,導致reduce的負載不均衡

  主要分為

    join

    group by

 

三:參考數據傾斜

1.鏈接

  https://my.oschina.net/leejun2005/blog/178631

 

2.前言

  在做Shuffle階段的優化過程中,遇到了數據傾斜的問題,造成了對一些情況下優化效果不明顯。

  主要是因為在Job完成后的所得到的Counters是整個Job的總和,優化是基於這些Counters得出的平均值,而由於數據傾斜的原因造成map處理數據量的差異過大,

  使得這些平均值能代表的價值降低。Hive的執行是分階段的,map處理數據量的差異取決於上一個stage的reduce輸出,所以如何將數據均勻的分配到各個reduce中,就是解決數據傾斜的根本所在。

 

3.操作

  其實就兩種,因為,count distinct的底層就是group by。

  

 

4.原因 

  1)、key分布不均勻

  2)、業務數據本身的特性

  3)、建表時考慮不周

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

 

5.表現

  任務進度長時間維持在99%,查看任務監控頁面,發現只有少量的reduce子系統未完成。

  單一的reduce的記錄與平均記錄差距過大,通常達到3倍甚至更多。

 

四:解決方案

1.主要針對的group by

  map的combiner

  hive.groupby.skewindata

  替換值,將不要的值替換掉,然后過濾掉。

 

2.參數調節

  )hive.map.aggr=true

  map端的combiner,提前聚合一下。

  

  )hive.groupby.skewindata=true

  不按照key進行分區,map端的結果到了reduce后就進行一次聚合,達到reduce負載均衡。

  這時,再進行一次mapreduce,group by key 分布到reduce,實現最終的聚合。

 

2.SQL調節 

  )如何Join

    關於驅動表的選取,選用join key分布最均勻的表作為驅動表

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

  )大小表Join

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

  )大表Join大表:

    把空值的key變成一個字符串加上隨機數,把傾斜的數據分到不同的reduce上,由於null值關聯不上,處理后並不影響最終結果。

  )count distinct大量相同特殊值

    count distinct時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最后結果中加1。

    如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。

  )group by維度過小:

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

 

五:業務場景(實際中會遇到的情況)

1.空值產生數據傾斜

  )過濾

  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;

 )賦予新的值

 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;

  )比較

    方法2比方法1效率更好,不但io少了,而且作業數也少了。

    解決方法1中 log讀取兩次,jobs是2。解決方法2 job數是1 。

    2適合無效 id (比如 -99 , ’’, null 等) 產生的傾斜問題。把空值的 key 變成一個字符串加上隨機數,就能把傾斜的數據分到不同的reduce上 ,解決數據傾斜問題。

 

2.不同的數據類型進行關聯

   )原因

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

   )把數字類型轉換成字符串類型

    select * from users a

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

3.表不大不小

  )解決

  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;
 

 

 


免責聲明!

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



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