数据倾斜就是在分布式计算的时候,数据的分散度不够,导致大量的数据集中到一台或几台机器上计算,导致整个任务的计算速度及效率大大下降。本文主要分析出现数据倾斜的原因及解决方案。
数据倾斜的原理及体现
在MapReduce
的shuffle阶段,将相同的key
拉取到一个Reduce
上计算,若某一种key
的数据量远远大于其他的key
的数据量,造成某一个Reduce Task
计算量过大,计算耗时较长,导致整个任务的计算速度及效率大大下降。因此数据倾斜一般有两种表现:① 大部分Reduce Task
执行完成特别快,某一个Reduce Task
执行特别慢,耗时长;② 某一个Reduce Task
出现OOM
,内存溢出,任务失败。
解决方案
MapReduce
中的数据倾斜解决方案
- 自定义
combiner
类。在map shuffle
阶段对数据压缩,相当于做一次Reduce
,相同的key先进行聚合运算。从而减少流向Reduce
端的文件数量和数据量。 - 分析导致数据倾斜的
key
,在Map
阶段将造成倾斜的key
分成多组,例如aaa
这个key
,map
时随机在aaa
后面加上 1,2,3,4 这四个数字之一,把key
先分成四组,先进行一次运算,之后再恢复 key 进行最终运算。
Hive
中数据倾斜的解决方案
- 参数调优
1
2set hive.map.aggr = true;
set hive.groupby.skewindata = true;
hive.map.aggr = true;
在Map
中做部分聚集操作,效率更高且需要更多的内存。hive.groupby.skewindata = true;
数据倾斜时会进行负载均衡,当选项设定为true
,生成的查询计划会有两个MapJob
。第一个MRJob
中,Map
的输出结果集合会随机分布到Reduce
中,每个Reduce
做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key
有可能被分发到不同的Reduce
中,从而达到负载均衡的目的;第二个MRJob
再根据预处理的数据结果按照GroupBy Key
分布到Reduce
中(这个过程可以保证相同的GroupBy Key
被分布到同一个Reduce
中),最后完成最终的聚合操作。
join
操作中,驱动表的选取
1) 选取key
分布均匀的表作为join
的驱动表;做好列裁剪和过滤操作,以到达两个表join
时,数据量相对变小的效果。
2) 大小表join
时,使用map join
时,让小维度表现进入内存。
3) 大表join
大表时,把空值的key
变成一个字符串加随机数,把倾斜的数据分布到不同的Reduce
上,由于null
值关联不上,处理后并不理解结果。- 能先进行
gourp by
操作的先进行gourp by
操作,把key
先进行一次Reduce
之后再进行count
或者distinct count
操作。