Hive中未经优化的分组聚合,是通过一个MapReduce Job实现的。
Map端负责读取数据,并按照分组字段分区,通过Shuffle,将数据发往Reduce端,各组数据在Reduce端完成最终的聚合运算。
如果group by分组字段的值分布不均,就可能导致大量相同的key进入同一Reduce,从而导致数据倾斜问题。
分组聚合导致
Map-Side聚合
Skew-GroupBy优化
Skew-GroupBy的原理是启动两个MR任务
第一个MR按照随机数分区,将数据分散发送到Reduce,完成部分聚合
第二个MR按照分组字段分区,完成最终聚合
--启用分组聚合数据倾斜优化
set hive.groupby.skewindata=true;
join操作导致
map join
使用map join算法,join操作仅在map端就能完成
没有reduce阶段,自然不会产生reduce端的数据倾斜
该方案适用于大表join小表时发生数据倾斜的场景
skew join
skew join的原理是:
为倾斜的大key单独启动一个map join任务进行计算,其余key进行正常的common join
--启用skew join优化
set hive.optimize.skewjoin=true;
--触发skew join的阈值,若某个key的行数超过该参数值,则触发
set hive.skewjoin.key=100000;
这种方案对参与join的源表大小没有要求,但是对两表中倾斜的key的数据量有要求,要求一张表中的倾斜key的数据量比较小(方便走mapjoin)。
调整SQL语句
添加随机数打散
假设原始SQL语句如下:A,B两表均为大表,且其中一张表的数据是倾斜的。
hive (default)>
select
*
from A
join B
on A.id=B.id;
调整SQL语句如下:
hive (default)>
select
*
from(
select --打散操作
concat(id,'_',cast(rand()*2 as int)) id,
value
from A
)ta
join(
select --扩容操作
concat(id,'_',0) id,
value
from B
union all
select
concat(id,'_',1) id,
value
from B
)tb
on ta.id=tb.id;