描述
数据倾斜是进行大数据计算时最经常遇到的问题之一。当我们在执行 Hive
z 语句或者运行MapReduce
job时候,如果遇到一直卡在map100%
,reduce99%
一般就 是遇到了数据倾斜。在进行分布式计算的时候,某些节点的计算能力比较强或者需要计算的数据比较少,所有很快执行完成,某些节点计算的能力较差或者由于此节点需要计算的数据比较多,导致其他节点的 reduce 阶段完成,自己的数据处理还没有结束。
hive 中产生数据倾斜的原因
建表时考虑不周
key 分布不均匀
业务数据本身的特性
些 SQL 语句问题
数据倾斜解决办法
大小表join
1、小表join大表,使用map join让小的维度表(1000条以下的记录条数) 先进内存,在map端完成reduce。
select /*+ MAPJOIN(smalltable)*/ key,... from smalltable join bigtable
on smalltable.key = bigtable.key
--hive0.11之后默认开启
hive.auto.convert.join=true 默认
hive.mapjoin.smalltable.filesize=2500000 默认
2、大表join大表:
主要是由于key的值为空值或0的居多,把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。
例如:case when 字段 is null then concat('字段',rand()) else 字段 end;
group by
当按照类型进行 group by
的时候,会将相同的 group by
字段的 reduce
任务需要的数据拉取到同一个节点进行聚合,而当其中的某些组的数据量过大时,group by
维度过小。
开启 Map
端聚合参数设置hive.map.aggr=true
(Map
端部分聚合,相当于Combiner
)
采用sum() group by的方式来替换count(distinct)完成计算。)
count(distinct …)
数据量过大,使用 sum(1)...group by
代替
如果是计算count distinct
,可以不用处理,直接过滤,在最后结果中加1。如果还有其他计算,需要进行group by
,可以先将值为空的记录单独处理,再和其他计算结果进行union。
参数调节
hive.groupby.skewinda=true
有数据倾斜产生的时候进行负载均衡,当选项设定为 true
,查询计划会生成有两个mapreduce
Job,Map 的输出结果集合会随机分布到 reduce 中,每个 reduce 做部分聚合,并输出结果,这样处理的结果是相同的 key 有可能被分发到不同的 reduce 中,减小数据组之后的负载均衡。
第二个mapreduce
Job再根据第一个reduce产生的数据结果按照 key 分布到 reduce 中,完成最后的聚合操作。