数据倾斜

零、回顾mr

以经典WordCount为例
在这里插入图片描述
由图中可以看到,在shuffle的时候,必须将各个节点相同的key拉取到某一个节点进行task的处理,比如:join\group by,如果某个key对应的数据量非常大,那么必然这个key对应的数据进行处理的时候就会产生数据倾斜。
凡是涉及到shuffle的操作,都有可能出现数据倾斜

一、现象

  • 任务进度长时间维持在99%(或100%)。查看任务监控页面,绝大多数task执行得都非常快,但个别task执行极慢。因为其处理的数据量和其他reduce差异过大。比如,总共有1000个task,997个task都在1分钟之内执行完了,但是剩余两三个task却要一两个小时。10个人干活,一个人干90%,9个人在边上看着,对于团队来说效率可不慢吗~~~木桶定理
  • 某天突然报出OOM(内存溢出)异常。观察异常栈,是我们写的业务代码造成的。突然让干几倍的活,可不给逼疯了~~~

二、产生原因

本质:map 输出数据按 key 的Hash 分配到 reduce 中,由于以下原因造成的 reduce 上的数据量差异过⼤。

  • key分布不均匀
  • 业务数据本身特性
  • 建表考虑不周
  • 某些sql语句本身就有数据倾斜

三、操作:

凡是涉及到shuffle的操作,都有可能出现数据倾斜,下面的可能不全哦~~~

  • join
    • 一个表小但key集中分发到某一个或几个Reduce上的数据远高于平均值
    • 都是大表,但空值过多这些空值都由一个reduce处理,非常慢
  • group by
    • 维度过小,处理某值的reduce非常慢处理某值的reduce非常耗时
  • count distinct
    • 特殊值过多处理此特殊值的reduce耗时

四、解决

本质是如何将数据均匀分配到各个reduce中

参数调节

  • hive.map.aggr=true map端聚合,相当于combiner
  • hive.groupby.skewindata=true 有数据倾斜的时候进行负载均衡,两个MR job,第一个随机分配map结果,从而达到负载均衡的目的,局部聚合;第二个按照 Group By Key 分布到 Reduce 中,最终聚合

sql优化

  • 减少数据量,列裁剪和fillter不需要的列就不要了,以达到两表做join的时候,数据量相对变小的效果
SELECT a.id
FROM bigtable a
LEFT JOIN ori b ON a.id = b.id
WHERE b.id <= 10;
--改写成
SELECT a.id
FROM ori a
LEFT JOIN bigtable b ON (a.id <= 10 AND a.id = b.id);
--或者直接改写成子查询
SELECT a.id
FROM bigtable a
RIGHT JOIN (SELECT id
			FROM ori
			WHERE id <= 10
			) b 
ON a.id = b.id;
  • 大小表join,小表先进内存,在map端完成reduce(新的版本当中已经没有区别了,旧的版本当中需要使用小表)
  • 大大表join,空值变字符串加随机数,分散到不同reduce,null关联不上,所以不影响最终结果
select *
from log a
left join users b
on case when a.user_id is null
		then concat('hive',rand())
		else a.user_id
	end = b.user_id
  • count(distinct)大量相同值采用sum() group by的方式来替换count(distinct)完成计算
    • 将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1;如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理其他计算结果进行union
 select *
 from log a
 join 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;
  • group by维度过小:选择一个具有分散的字段 b,按照a,b聚合,得到一个比较小的中间结果集 ,再group by a
select a,count(distinct b) as c from tb_name group by a;
--改写成
select a,count(*) as c 
from (select a,b 
      from tb_name 
      group by a,b
    )
group by a;
  • 特殊情况特殊处理:
    • 在业务逻辑优化效果的不大情况下,有些时候是可以将倾斜的数据单独拿出来处理。最后union回去。

五、扩展

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

  • 问题:不同数据类型 id 的关联会产生数据倾斜问题。
  • 一张表 s8 的日志,每个商品一条记录,要和商品表关联。但关联却碰到倾斜的问题。 s8 的日志中有 32 为字符串商品 id,也有数值商品 id,日志中类型是 string 的,但商品中的 数值 id 是 bigint 的。猜想问题的原因是把 s8 的商品 id 转成数值 id 做 hash 来分配 Reduce, 所以字符串 id 的 s8 日志,都到一个 Reduce 上了,解决的方法验证了这个猜测。
  • 解决方法:把数据类型转换成字符串类型
SELECT * 
FROM s8_log a 
LEFT OUTER JOIN r_auction_auctions b 
	ON a.auction_id=CAST(b.auction_id AS STRING) 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值