數倉--Hive-面試之Hive數據傾斜的原因及主要解決方法

對於參數命令的記憶,需要固定在

數據傾斜產生的原因

數據傾斜的原因很大部分是join傾斜和聚合傾斜兩大類

Hive傾斜之group by聚合傾斜

  • 原因:
    • 分組的維度過少,每個維度的值過多,導致處理某值的reduce耗時很久;
    • 對一些類型統計的時候某種類型的數據量特別多,其他的數據類型特別少。當按照類型進行group by的時候,會將相同的group by字段的reduce任務需要的數據拉取到同一個節點進行聚合,而當其中每一組的數據量過大時,會出現其他組的計算已經完成而這個reduce還沒有計算完成,其他的節點一直等待這個節點的任務執行完成,所以會一直看到map 100% reduce99%的情況;
  • 解決方法:
    • set hive.map.aggr=true;
    • set hive.groupby.skewindata=true;
  • 原理:
    • hive.map.aggr=true 這個配置代表開啓map端聚合;
    • hive.groupby.skewindata=true,當選項設定爲true,生成的查詢計劃會有兩個MR Job。當第一個MR Job中,Map的輸出結果結合會隨機分佈到Reduce中,每個Reduce做部分聚合操作,並輸出結果。這樣處理的結果是相同的Group By Key有可能被分發到不同的Reduce中,從而達到負載均衡的目的。第二個MR Job再根據預處理的數據結果按照Group By Key分佈到reduce中,這個過程可以保證相同的key被分到同一個reduce中,最後完成最終的聚合操作。
    • 【大數據開發學習資料領取方式】:加入大數據技術學習交流羣458345782,點擊加入羣聊,私信管理員即可免費領取

Hive傾斜之Map和Reduce優化

  • 1-原因:當出現小文件過多,需要合併小文件。可以通過set hive.merge.mapredfiles=true來解決;
  • 2-原因:輸入數據存在大塊和小塊的嚴重問題,比如 說:一個大文件128M,還有1000個小文件,每 個1KB。 解決方法:任務輸入前做文件合併,將衆多小文件合併成一個大文件。通過set hive.merge.mapredfiles=true解決;
  • 3-原因:單個文件大小稍稍大於配置的block塊的大小,此時需要適當增加map的個數。解決方法:set mapred.map.tasks的個數;
  • 4-原因:文件大小適中,但是map端計算量非常大,如:select id,count(*),sum(case when...),sum(case when ...)...需要增加map個數。解決方法:set mapred.map.tasks個數,set mapred.reduce.tasks個數;

Hive傾斜之HQL中包含count(distinct)時

  • 如果數據量非常大,執行如select a,count(distinct b) from t group by a;類型的sql時,會出現數據傾斜的問題。
  • 解決方法:使用sum...group by代替。如:select a,sum(1) from(select a,b from t group by a,b) group by a;

Hive傾斜之HQL中join優化

  • 當遇到一個大表和一個小表進行join操作時。使用mapjoin將小表加載到內存中。如:select /*+ MAPJOIN(a) */ a.c1, b.c1 ,b.c2 from a join b where a.c1 = b.c1;
  • 遇到需要進行join,但是關聯字段有數據爲null,如表一的id需要和表二的id進行關聯;
    • 解決方法1:id爲null的不參與關聯
      比如:
select * from log a 
 join users b 
on a.id is not null and a.id = b.id 
union all 
select * from log a 
where a.id is null; 
  • 解決方法2: 給null值分配隨機的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; 

合理設置Map數

對上文描述的總結

  • 1)通常情況下,作業會通過input的目錄產生一個或者多個map任務。
    主要的決定因素有:input的文件總個數,input的文件大小,集羣設置的文件塊大小。
  • 2)是不是map數越多越好?
    答案是否定的。如果一個任務有很多小文件(遠遠小於塊大小128m),則每個小文件也會被當做一個塊,用一個map任務來完成,而一個map任務啓動和初始化的時間遠遠大於邏輯處理的時間,就會造成很大的資源浪費。而且,同時可執行的map數是受限的。
  • 3)是不是保證每個map處理接近128m的文件塊,就高枕無憂了?
    答案也是不一定。比如有一個127m的文件,正常會用一個map去完成,但這個文件只有一個或者兩個小字段,卻有幾千萬的記錄,如果map處理的邏輯比較複雜,用一個map任務去做,肯定也比較耗時。
  • 針對上面的問題2和3,我們需要採取兩種方式來解決:即減少map數和增加map數;

未完待補充,根據實際開發經歷進行補充


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章