MapReduce任務(wù)中,Map輸出數(shù)據(jù)按Key Hash分配到Reduce中,由于Key分布不均勻、業(yè)務(wù)數(shù)據(jù)本身的特性、建表時考慮不周、某些SQL語句本身就有數(shù)據(jù)傾斜等原因造成的reduce上的數(shù)據(jù)量差異過大,如何將數(shù)據(jù)均勻的分配到各個Reduce中,就是解決數(shù)據(jù)傾斜的根本所在,舉三個例子
Map 端聚合
-- 設(shè)置如下參數(shù)即可開啟map端聚合,就是在Map端將相同的Key先做一次聚合計算,減少往reduce發(fā)送的數(shù)據(jù)
set hive.map.aggr=true
GroupBy 產(chǎn)生的數(shù)據(jù)傾斜
-- 設(shè)置如下參數(shù),在GroupBy時,生成兩個Job,第一個Job給GroupBy的key加隨機數(shù),隨機分布到Reduce中,每個Reduce做
部分聚合操作,先縮小數(shù)據(jù)量。第二個Job再進行真正的數(shù)據(jù)處理,完成最終的聚合
set hive.groupby.skewindata = true
count(distinct)
-- count(distinct) 數(shù)據(jù)傾斜,可以使用 sum + groupby 來完成等價轉(zhuǎn)換,
-- 原始SQL
select count(distinct uuid) from t1;
-- 等價轉(zhuǎn)換SQL, 其實就是采用分治思路,我們按照uuid的前n位進行GROUP BY,并做COUNT(DISTINCT )操作,
然后再對所有的COUNT(DISTINCT)結(jié)果進行求和
select sum(agg_part) result from
(
select substr(uuid,1,3) uuid_part,
count(distinct substr(uuid,4)) as agg_part
from t1
group by substr(uuid,1,3)
)t