Hive数据倾斜

      关于hive数据倾斜的问题,一直是我们老生常谈的问题,那么如何能把这个问题回答的富有逻辑性并且较为全面的,是需要好好去整理和归纳自己的思路的。毕竟产生数据的场景不同,相应的我们的解决办法也会有所不同。当然要适当的去举实际场景中的例子增加我们对理论的融会贯通程度。

    主要分为map端倾斜和reduce端倾斜,map端倾斜主要是因为输入文件大小不均匀导致,造成部分数据大量的集中在某一个节点上,形成了数据热点,导致这一节点运行时间远远大于其他节点的时间,reduce端主要是partition不均匀导致。

配置方面

1.场景:输入数据存在大块和小块的严重问题,有就是小文件过多,比如 说:一个大文件128M,还有1000个小文件,每 个1KB

解决办法:设置参数set hive.merge.mapredfiles=true,任务输入前做文件合并,将众多小文件合并成一个大文件

2.场景:当单个文件大小稍大于block的大小可以适当的增加map的个数

set mapred.map.tasks个数

大小表关联

在进行大小表join,小表在左,大表在右,left join 尽量以左边为主,右表只取我想要的数据

或者或使用mapjoin 将小表加载到内存中。然后再对比较大的表进行map操作,这样的话聚合操作就是在map端完成,因为map端的优势就是没有shuff

大量key值为null

null值的数据就会统一分布在一个节点,导致节点运行时间过长

解决方法1:子查询中过滤掉null值,id为空的不参与关联(前提是过滤掉的数据意义不是很大)

select * from log a join user b on a.user_id is not null and a.user_id = b.user_id union all select * from log c where c.user_id is null

解决方法2:用case when给空值分配随机的key值(字符串+rand())

select * from log a left outer join user b on case when a.user_id is null then concat('hive',rand()) else a.user_id end = b.user_id

相比较而言,还是方法2的效率要比方法1的效率要更高些,不但 IO 少了,而且作业数也少了,方案 1 中,log 表 读了两次,jobs 肯定是 2,而方案 2 是 1。这个优化适合无效 id(比如-99,’’,null)产 生的数据倾斜,把空值的 key 变成一个字符串加上一个随机数,就能把造成数据倾斜的 数据分到不同的 reduce 上解决数据倾斜的问题。

总结:通过改变null值,让其不在拥挤在同一个maptask中

不同数据类型关联产生数据倾斜

场景:用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时,默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配到一个Reducer中

解决方法:把数字类型转换成字符串类型

select * from users a left outer join logs b on a.usr_id = cast(b.user_id as string)

HiveQL中包含count(distinct)

当数据量非常大时,使用去重是完全禁止的

select a,count(distinct b) from t group by a;

解决办法:改用group by

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值