Hive的过程中经常会碰到数据倾斜问题,数据倾斜基本都发生在group、join等需要数据shuffle的操作中,这些过程需要按照key值进行数据汇集处理,如果key值过于集中,在汇集过程中大部分数据汇集到一台机器上,这就会导致数据倾斜。
具体表现为:作业经常reduce完成在99%后一直卡住,最后的1%花了几个小时都没有跑完。
常见产生数据倾斜的原因:
1、 空值产生的数据倾斜场景:
如日志中,常会有信息丢失的问题,比如全网日志中的user_id,如果取其中的user_id和bmw_users关联,会碰到数据倾斜的问题。
解决方法1:
user_id为空的不参与关联
select *
from log a
join bmw_users b
on a.user_id is not null
and a.user_id = b.user_id
union all
select *
from log a
where a.user_id is null;
解决方法2 :
赋与空值分新的key值(推荐)
select *
from logs a
left join bmw_users b
on case when a.user_id is null then concat(‘dp_hive’,rand() ) else a.user_id end = b.user_id;
2、 不同数据类型关联产生数据倾斜场景:
用户表中user_id字段为int,logs表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的join操作时,默认的Hash操作会按照int型的id来进行分配,这样会导致所有string类型的id记录都分配到同一个reduce中。
解决方法:
把数字类型转换成字符串类型
select *
from users a
left join logs b
on a.user_id = cast(b.user_id as string)
3、关联的key非空,但是某个key值大量重复
解决方法:
加入随机数
select a.key as key, b.pv as pv
from(
select key
from table1
where dt='2018-06-18') a
left join(
select key, sum(pv) as pv
from (
select key, round(rand()*1000) as rnd, #加入随机数,增加并发度
count(1) as pv
from table2
where dt='2018-06-18' group by key,rnd) tmp
group by key) b
on a.key = b.key
4、distinct、count(distinct)
解决方法:
用group by 去重
#distinct替换:
原始sql:
select distinct key from A;
替换后的sql:
select key from A group by key;
#单维度count(distinct)替换
原始sql:
select ship_id, count(distinct order_id) as ship_order_num
from table A
where dt = '2018-06-18'
group by ship_id;
替换后的sql:
select ship_id, count(1) as ship_order_num
from
(select ship_id, order_id
from table A
where dt = '2018-06-18'
group by ship_id, order_id) t
group by ship_id;
#多维度count(distinct)替换 —每个维度单独处理后关联