都是HIVE数据倾斜惹的祸

症状和原因:
  • 操作:join,group by,count distinct 
  • 原因:key分布不均匀,人为的建表疏忽,业务数据特点。
  • 症状:任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成;查看未完成的子任务,可以看到本地读写数据量积累非常大,通常超过10GB可以认定为发生数据倾斜。
  • 倾斜度:平均记录数超过50w且最大记录数是超过平均记录数的4倍;最长时长比平均时长超过4分钟,且最大时长超过平均时长的2倍。
我遇到的问题:
select * from a join b;
1. a表1000多万,b表不到2亿,用mapjoin显然不行;
2. 设置参数 set hive.groupby.skewindata=true,不起作用;
3. 由于关连键为手机号,自认为业务数据上不存在数据倾斜;

后来通过查看每个表里面关联键的分布,才发现两个表里面都存在空串'',而且严重倾斜,大表里面的空串数量有400多万。
将两个表的空串过滤后再进行关联,job时间由原来的40多分钟减少到2分钟。

总结:
 1. 数据倾斜的原因就那么几种,逐一排查;
 2. 细心,动手,不能光凭感觉来判定;
 3. 判定某一个表的key是否存在数据倾斜,就是group by key,取top N来看;

附:数据倾斜常用解决方法:

1. 万能膏药:hive.groupby.skewindata=true
2. 大小表关联:将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的机率;再进一步,可以使用map join让小的维度表(1000条以下的记录条数)先迚内存。在map端完成reduce.
3. 大表和大表关联:把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。
4. count distinct大量相同特殊值:count distinct时,将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1。如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union。




当该字段存在大量值为null或空的记录,容易发生数据倾斜;


解决思路:
count distinct时,将值为空的情况单独处理, 如果是计算 count distinct ,可以不用处理,直接过滤,在最后结果中加1 ;
如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union。

案例:
select count(distinct  end_user_id) as user_num  from trackinfo;
调整为:
select cast(count(distinct end_user_id)+1 as bigint) as user_num  from trackinfo where  end_user_id is not null and end_user_id <> '';
分析:把为空的过滤掉,在总的count上加1


Multi-Count Distinct

select pid, count(distinct acookie),count(distinct ip),count(wangwangid ip) from ods_p4ppv_ad_d where dt=20140305 group by pid;
必须设置参数:set hive.groupby.skewindata=true
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章