数据倾斜

1.数据倾斜是进行大数据计算时,最常遇到的问题之一,当我们在执HiveQL 或者运行MR作业时,如果遇到一直卡在map 100% ,reduce99%,最后的1% 花了几个小时都没有跑完,这种情况一般就是遇到了数据倾斜的问题.

2.数据倾斜其实是进行分布式计算的时候,某些节点计算的能力较差,或者由于此节点需要计算的数据比较多,导致出现其他节点的reduce阶段任务执行完成,但是这种节点的数据处理任务还没有执行完成。

什么是数据倾斜

简单来说数据倾斜就是key的分化严重不均,造成一部分数据很多,一部分数据很少的局面。

举个例子:
比如wordCount,它的map阶段,形成了(“aaa”,1)的形式,然后在reduce阶段进行value相加,得出"aaa"出现的次数。若进行wordCount的文本有100G,其中80G全部是"aaa",剩下20G根据key不同分散到不同的reduce,进行相加的情况,如此造成了数据倾斜

数据倾斜_第1张图片

通过上面这个图,能清楚的看到,数据经过map之后,由于key的数据量分布不均,在Shuffle阶段中,通过分组将相同的key的数据打在同一个reducer的标记,然后开始spill(一些到磁盘),最后么个人成最终map阶段输出文件。

造成数据倾斜的原因

1.key分布不均
2.业务数据本身的特性
3.建表时考虑不周
4.某些SQL语句本身就有数据倾斜

数据倾斜的影响

hadoop中数据倾斜会极大影响性能和效率

数据倾斜的表现

任务进度长时间维持在99%,查看任务监控页面,发现只有少量(1个或者几个),处理的数据量和其它reduce差异过大

单一reduce的记录数于平均记录数差异过大,通常可能达到3倍甚至更多,最长时长大于平时时长。

Hive中产生数据倾斜的原因和解决办法

1)group by , 我使用Hive对数据做一些类型统计的时候遇到过某些类型的数据量特别多,而其他类型数据的数据量特别少,当 按照类型进行group by的时候,会将相同的group by 字段reduce的任务需要的数据拉取到同一个节点进行聚合,而当其中每一组的数据量过大的时候,会出现其他组的计算已经完成而这里计算还没有完成,其它节点的一直等待这个节点 的任务执行完成,所以会一直看到map 100% reduce 99%的情况。

解决办法:
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中(这个过程可以保证相同的Group By Key 被分布到Reduce中),最后完成最终的聚合操作。

2)map和 reduce优化
1.当出现小文件过多,需要合并小文件,
解决: set hive.merge.mapfiles=true
2.单个文件大小稍稍大于配置的block的大小,此时需要适当增加map的个数
解决:set mapred.map.tasks个数
3.文件大小适中,但是map端的计算量非常大,如select id,count(*),sum(case when),sum(case when) 需要增加map 个数
解决:set mapred.reduce.tasks个数

3)当HiveQL中包含count(distinct)时,如果数据量非常大,执行select a,count(distinct b) from group by a;类型的SQL时,会出现数据倾斜的问题
解决办法:使用sum…group by 代替,eg:select a,sum(1) from (select a,b from t group by a,b) group by a;
4)当遇到一个打标和一个小表join操作时。
解决办法:使用mapjoin将小表加载到内存中。
select /*+MAPJOIN(a) * / a.c1,b.c1,b.c2 from a join b where a.c1 = b.c1
5)遇到需要进行join的但是关联字段有数据为空,如表一的id,需要和表二的id进行关联
解决办法1:id为空的不参与关联
eg:
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:给空值分配随机的key值
eg: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

你可能感兴趣的:(数据倾斜)