Hive的数据倾斜处理方案

1、什么是数据倾斜?

由于数据分布不均匀,造成数据大量的集中到一点,造成数据热点

2、Hadoop 框架的特性

A、不怕数据大,怕数据倾斜

B、Jobs 数比较多的作业运行效率相对比较低,如子查询比较多

C、 sum,count,max,min 等聚集函数,通常不会有数据倾斜问题

3、主要表现

任务进度长时间维持在 99%或者 100%的附近,查看任务监控页面,发现只有少量 reduce 子任务未完成,因为其处理的数据量和其他的 reduce 差异过大。 单一 reduce 处理的记录数和平均记录数相差太大,通常达到好几倍之多,最长时间远大 于平均时长。

4、容易数据倾斜情况

join:
其中一个表小,但是key集中
大表与大表,但是分同的判断字段0值或空值过多
group by:
维度过小,某值得数量过多
count(distinct):
某特殊值过多

A。 小表关联超大表 join
B。 group by 不和聚集函数搭配使用的时候
C。 count(distinct),在数据量大的情况下,容易数据倾斜,因为 count(distinct)是按 group by 字段分组,按 distinct 字段排序

5、解决方案

(1)空值产生的数据倾斜

case when a.user_id is null then concat('hive',rand())

把空值的 key 变成一个字符串加上一个随机数,就能把造成数据倾斜的 数据分到不同的 reduce 上解决数据倾斜的问题。

(2)大小表关联查询产生数据倾斜
注意:使用map join解决小表关联大表造成的数据倾斜问题。
map join 概念:将其中做连接的小表(全量数据)分发到所有 MapTask 端进行 Join,从 而避免了 reduceTask,前提要求是内存足以装下该全量数据

select /* +mapjoin(a) */ a.id aid, name, age from a join b on a.id = b.id;

(3)不同数据类型关联产生数据倾斜
用户表中 user_id 字段为 int,log 表中 user_id 为既有 string 也有 int 的类型, 当按照两个表的 user_id 进行 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)

(4)当HiveQL中包含count(distinct)时
如果数据量非常大,执行如select a,count(distinct b) from t group by a;类型的SQL时,会出现数据倾斜的问题。
解决方法:使用sum…group by代替。如:

select a,sum(1) from (select a, b from t group by a,b) group by a;

(5)调节hive配置参数
设置hive.map.aggr = true map端部分聚合,相当于Combiner
设置hive.groupby.skewindata = true 有数据倾斜时,查询计划生成两个mr job, 第一个job先进行key随机分配处理,先缩小数据量。第二个job再进行真正的group by key处理。

猜你喜欢

转载自blog.csdn.net/weixin_42135152/article/details/85755684