hive数据倾斜
一、什么是数据倾斜
由于数据分布不均匀,造成数据大量集中在一起,造成数据热点
二、Hadoop框架的特性
A、不怕数据大,就怕数据倾斜
B、 jobs数目较多的作业运行效率相对较低
C、sum,count,max,min等聚集函数,通常不会有数据倾斜
三、主要表现
任务进度长时间维持在99%或100%的附近,查看任务监控页面,发现只有少量reduce子任务未完成,因为其处理的数据量和其他的reduce差异过大。单一reduce处理的记录数和平均记录数相差太大,通常达到几倍之多,最大时间远大于平均时长
四、造成数据倾斜的原因
A. group by 不和聚集函数搭配使用
B. count(distinct),在数据量大的情况下,容易数据倾斜,因为count(distinct)是按group by字段分组,按distinct字段排序
C. 小表关联超大表join
五、产生数据倾斜的原因
A:key 分布不均匀
B:业务数据本身的特性
C:建表考虑不周全
D:某些 HQL 语句本身就存在数据倾斜
六、场景
(1)空值产生的数据倾斜
在日志中,常会有信息丢失的问题,比如日志中的 student_id,如果取其中的 student_id 和用户表中的 student_id 相关联,就会碰到数据倾斜的问题。
解决办法:
方案1:student_id为空的不参与关联
select * from log a
join students b
on a.student_id is not null
and a.student_id = b.student_id
union all
select * from log a
where a.student_id is null;
方案2:给空值赋新的key值
select *
from log a
left outer join students b
on case when a.student_id is null then concat(‘hive’,rand() ) else a.student_id end = b.student_id;
(2)不同数据类型造成数据倾斜
解决方案:把数字类型转换为字符串类型
select * from students a
left outer join logs b
on a.student_id = cast(b.student_id as string)
(3)大小表关联
情形一:一张大表,一张小表,此时应使用map join来处理(hive0.1.1之前需要强制开启map join,hive0.1.1之后的版本会自动开启map join)
情形二:两张大表关联,此时应该先把大表切分成小标,然后分别map join
情形三:小表不大也不小,此时不适合采用普通的join
改进方法:
select /*+mapjoin(x)*/* from log a
left outer join (
select /*+mapjoin(c)*/d.*
from ( select distinct student_id from log ) c
join students d
on c.student_id = d.student_id
) x
on a.student_id = b.student_id;
七、总结
大量经验表明数据倾斜的原因表明是人为的建表疏忽或着业务逻辑可以规避的,常用的步骤为:
1、采样log表,哪些student_id比较倾斜,得到一个结果表tmp1。由于对计算框架来说,所有的数据过来,他都是不知道数据分布情况的,所以采样是并不可少的。
2、数据的分布符合社会学统计规则,贫富不均。倾斜的key不会太多,就像一个社会的富人不多,奇特的人不多一样。所以tmp1记录数会很少。把tmp1和students做map join生成tmp2,把tmp2读到distribute file cache。这是一个map过程。
3、map读入students和log,假如记录来自log,则检查student_id是否在tmp2里,如果是,输出到本地文件a,否则生成