一、hive.groupby.skewindata
set hive.groupby.skewindata=true;
数据倾斜时负载均衡,当选项设定为true,生成的查询计划会有两个MRJob。第一个MRJob 中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作。
由上图下部分过程可看到过程,由此带出解决数据倾斜的方式。
二、关于数据倾斜出现原因:
- 对于join过程来说,如果出项较多的key值为空或异常的记录,或key值分布不均匀,就容易出现数据倾斜。
- 对于group by 过程来说,如果某一个key值有特别的多的记录,其它key值的记录比较少,也容易出项数据倾斜。
Join实现原理举例:
select name, orderidf
from user t1
join order t2 on t1.uid=t2.uid
Group by实现原理举例
sql = select rank, isonline, count(1)
from city
group by 1, 2
三、数据倾斜的解决方案
①、join引起数据倾斜的解决方法
- 如果是由于key值为空或为异常记录,且这些记录不能被过滤掉的情况下,可以考虑给key赋一个随机值,将这些值分散到不同的reduce进行处理。
- 如果是一个大表和一个小表join的话,可以考虑使用mapjoin来避免数据倾斜。
mapjoin原理可参考前一篇文章:浅谈Hive中Map Join原理及场景
②、group by 引起数据倾斜的解决方法
set hive.map.aggr=true;
在map中会做部分聚集操作,效率更高但需要更多的内存。开启map之后使用combiner,这样基本上是对各记录比较同质的数据效果比较好,相反,则没有什么意义。通用的做法是设置下面两个参数:
set hive.groupby.mapaggr.checkinterval = 100000 (默认)执行聚合的条数
set hive.map.aggr.hash.min.reduction=0.5(默认)
#如果hash表的容量与输入行数之比超过这个数,那么map端的hash聚合将被关闭,默认是0.5,
#设置为1可以保证hash聚合永不被关闭;
还有一个方式是本文提及的set hive.groupby.skewindata=true
ps: 有博文反应该参数与set hive.map.aggr=true同时使用时候对distinct结果会有影响,但我实测并没有,可能是特定情况才会出现?如若碰到还请随时交流。hive.groupby.skewindata 和 hive.map.aggr 组合的坑
参考:
hive数据倾斜原理与解决方案
hive原理与源码分析
学习交流,有任何问题还请随时评论指出交流。