文章目录
倾斜现象
任务进度长时间卡在99% 有的时候甚至100%,查看任务监控页面.发现只有少量的reduce 子任务未完成,因为其处理的数据量和其他reduce 差异过大,单一reduce 记录数与平均记录数差异过大,最长时长远大于平均时长
产生场景
大部分发生在reduce阶段,较少发生在map阶段,map端的数据倾斜主要是hdfs存储块分布不均衡,reduce阶段数据倾斜几乎都是没有考虑到某种key值数据量较多场景
Reduce阶段最容易出现数据倾斜的两个场景分别是Join和Count
join阶段
- 其中一个表较小,但是key集中,后果是分发到某一个或几个reduce上的数据远高于平均值
- 大表与大表,但是分桶的判断字段0值或空值过多,空值都由一个reduce处理,非常慢
- group by 维度过小,某值的数量过多,处理某值的reduce耗时
- Count Distinct 某特殊值过多 造成处理此特殊值的reduce耗时
产生原因
- key分布不均匀
- 业务数据本身特性
- 建表时考虑不周
- 某些SQL语句本身就会数据倾斜
解决方案
开启负载均衡
-- map端的Combiner,默认为ture
set hive.map.aggr=true;
-- 开启负载均衡
set hive.groupby.skewindata=true (默认为false)
mapreduce进程会产生两个额外的MR job
第一步: MR Job 中Map输出结果集合首先会随机分配到Reduce 中,然后每个reduce 做局部聚合操作并输出结果,相同的group by key 可能分到不同reduce job中,达到负载均衡目的
第二步: MR job 在根据预处理数据结果,按照Group by Key 分布到reduce 中
(保证相同的group by key 被分布到同一个reduce中),最后完成聚合操作;
小表join大表,某个key过大
通常做法是将倾斜的数据存到分布式缓存中,分发到各个Map任务所在节点。在Map阶段完成join操作,即MapJoin,这避免了 Shuffle,从而避免了数据倾斜。
默认是自动开启
-- 自动开启MAPJOIN优化,默认值为true,
set hive.auto.convert.join=true;
-- 通过配置该属性来确定使用该优化的表的大小,如果表的大小小于此值就会被加载进内存中,默认值为2500000(25M),
set hive.mapjoin.smalltable.filesize=2500000;
使用默认启动该优化的方式如果出现莫名其妙的BUG(比如MAPJOIN并不起作用),就将以下两个属性置为fase手动使用MAPJOIN标记