目录
HIVE的数据倾斜
什么是数据倾斜
由于数据分布不均匀,造成大量的数据集中到一个分区里,造成数据热点
主要表现
当其他reduce运行结束后,有少量的reduce一直在计算,因为其中处理数据量是其他的几倍,所以计算时间就很长,是其他的几倍
出现数据倾斜的原因
key值分布不均匀
业务数据本身的特性
建表考虑不周到 :应该建立分区表没有建立
某些sql语句本身就存在数据倾斜
业务场景
空值产生的数据倾斜
联想男女,很多人可能提交个人资料的时候不填性别,这会造成有空值,当两个表相关联的时候,就会产生数据倾斜的问题
解决办法一:把不是null的提取出来放一个分区里,把null的放一个分区里
select * from log a join user b on a.gender is not null and a.gender = b.gender
union all
select * from log c where c.gender is null;
解决办法二:赋予空值新的key值
select * from log a left outer join user b on
case when a.gender is null then concat('gender',rand())
else a.gender end = b.gender
赋予空值,新的key值,效率更好,这种办法IO少了
使本身为null的所有记录不会拥挤在同一个reduceTask了,会分散到多个reduceTask中,由于null值关联不上,处理后并不影响结果
key分布极其不均匀,group时造成数据倾斜
就上面的案例来说,可能一个表中,男生7个,而女生只有一个,如果按性别分组计算的话,就容易出现数据倾斜
——> 所有数据会分别进入两个reduce节点中,而男性的节点数据量过大,计算非常缓慢。
解决办法:为key值加盐
1:与另一个字段组合,形成新字段,按新字段分组
2: 使用随机数与性别做组合,与上面的空值解决办法差不多
不同数据类型产生数据倾斜
比如有两张表,stu表有user_id为int,log表中user_id既有string,又有int,当进行join时,默认的hash操作会按照int类型的id去进行分配,string的id会被分配到另一个reducer中
解决方案:将数字类型id转换成string类型的id
select * from user a left outer join log b on b.user_id = cast(a.user_id as string)
大小表关联查询产生数据倾斜
小大表
以大表a和小表b为例,所有的mapTask节点装载小表b的数据,a1
和b做全量数据做连接,意思就是先使用mapjoin,先让小的维度表先进内存。在map端完成reduce
解决办法:将小表的数据放到maptask节点中,让小表进行map操作,这样就不用去reduce上做汇总,可以减少IO
具体操作
SET hive.auto.convert.join = true; //设置MapJoin优化自动开启
SET hive.mapjoin.smalltable.filesize=25000000//设置小表不超过多大时开启mapjoin优化
大大表
就将大表切分成小表,然后分别mapjoin

894

被折叠的 条评论
为什么被折叠?



