Hive傾斜之group by聚合傾斜
原因:
分組的維度過少悠夯,每個維度的值過多侠草,導致處理某值的reduce耗時很久翰撑;
對一些類型統(tǒng)計的時候某種類型的數(shù)據(jù)量特別多,其他的數(shù)據(jù)類型特別少匠题。當按照類型進行g(shù)roup by的時候尽超,會將相同的group by字段的reduce任務需要的數(shù)據(jù)拉取到同一個節(jié)點進行聚合,而當其中每一組的數(shù)據(jù)量過大時梧躺,會出現(xiàn)其他組的計算已經(jīng)完成而這個reduce還沒有計算完成,其他的節(jié)點一直等待這個節(jié)點的任務執(zhí)行完成傲绣,所以會一直看到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。當?shù)谝粋€MR Job中菠净,Map的輸出結(jié)果結(jié)合會隨機分布到Reduce中禁舷,每個Reduce做部分聚合操作,并輸出結(jié)果毅往。這樣處理的結(jié)果是相同的Group By Key有可能被分發(fā)到不同的Reduce中牵咙,從而達到負載均衡的目的。第二個MR Job再根據(jù)預處理的數(shù)據(jù)結(jié)果按照Group By Key分布到reduce中攀唯,這個過程可以保證相同的key被分到同一個reduce中洁桌,最后完成最終的聚合操作;
Hive傾斜之Map和Reduce優(yōu)化
- 原因:當出現(xiàn)小文件過多,需要合并小文件侯嘀×砹瑁可以通過set hive.merge.mapredfiles=true來解決谱轨;
- 原因:輸入數(shù)據(jù)存在大塊和小塊的嚴重問題,比如 說:一個大文件128M吠谢,還有1000個小文件土童,每 個1KB。 解決方法:任務輸入前做文件合并工坊,將眾多小文件合并成一個大文件献汗。通過set hive.merge.mapredfiles=true解決;
- 原因:單個文件大小稍稍大于配置的block塊的大小栅组,此時需要適當增加map的個數(shù)雀瓢。解決方法:set mapred.map.tasks的個數(shù);
- 原因:文件大小適中玉掸,但是map端計算量非常大刃麸,如:select id,count(*),sum(case when...),sum(case when ...)...需要增加map個數(shù)。解決方法:set mapred.map.tasks個數(shù)司浪,set mapred.reduce.tasks個數(shù)泊业;
Hive傾斜之HQL中包含count(distinct)時
如果數(shù)據(jù)量非常大,執(zhí)行如select a,count(distinct b) from t group by a;類型的sql時啊易,會出現(xiàn)數(shù)據(jù)傾斜的問題吁伺。
解決方法:使用sum...group by代替。如:select a,sum(1) from(select a,b from t group by a,b) group by a;
Hive傾斜之HQL中join優(yōu)化
當遇到一個大表和一個小表進行join操作時租谈。使用mapjoin將小表加載到內(nèi)存中篮奄。如:select /*+ MAPJOIN(a) */ a.c1, b.c1 ,b.c2 from a join b where a.c1 = b.c1;
遇到需要進行join,但是關聯(lián)字段有數(shù)據(jù)為null割去,如表一的id需要和表二的id進行關聯(lián)窟却;
解決方法1:id為null的不參與關聯(lián)
比如:
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數(shù)
- 通常情況下,作業(yè)會通過input的目錄產(chǎn)生一個或者多個map任務呻逆。
主要的決定因素有:input的文件總個數(shù)夸赫,input的文件大小,集群設置的文件塊大小咖城。 - 是不是map數(shù)越多越好茬腿?
答案是否定的。如果一個任務有很多小文件(遠遠小于塊大小128m)宜雀,則每個小文件也會被當做一個塊切平,用一個map任務來完成,而一個map任務啟動和初始化的時間遠遠大于邏輯處理的時間州袒,就會造成很大的資源浪費揭绑。而且,同時可執(zhí)行的map數(shù)是受限的。 - 是不是保證每個map處理接近128m的文件塊他匪,就高枕無憂了菇存?
答案也是不一定。比如有一個127m的文件邦蜜,正常會用一個map去完成依鸥,但這個文件只有一個或者兩個小字段,卻有幾千萬的記錄悼沈,如果map處理的邏輯比較復雜贱迟,用一個map任務去做,肯定也比較耗時絮供。
針對上面的問題2和3衣吠,我們需要采取兩種方式來解決:即減少map數(shù)和增加map數(shù);