Hive数据倾斜原因及解决方案

1、数据倾斜定义

数据分布不均,造成大量数据集中到一点,造成数据热点。

2、数据倾斜的表现

在执行任务的时候,任务进度长时间维持在99%左右;

查看stage的执行情况时,卡在最后1-2个task长时间不动,查看task监控页面,发现某个或某两三个task运行的时间远远大于其他task的运行时间,这些task处理的数据量也远远大于其他task。

注:一个spark任务的运行时间是由最后一个执行成功的task决定的,如果某个task发生了数据倾斜,会拖慢整个spark任务执行效率,即便其他没有倾斜的task已经执行完毕,甚至会导致OOM

3、查看数据倾斜方法

在yarn界面查看是否产生数据倾斜:
在这里插入图片描述
上图是yarn界面task的监控页面,从上图可以看出大部分task的执行时间是25s,处理记录数为几万到几十万不等(处理数据量大部分为几兆到几十兆),但是有一个task处理时间为1小时处理数据量高达72G且还没执行完,此时可以推断数据发生了倾斜,可以通过group by或者抽样找出倾斜key。

4、数据倾斜条件

数据计算时发生了shuffle,即对数据进行了重新分区。

关键词情形后果
join某个或某几个key比较集中,或者存在大量null key分发到某一个或者某几个Reduce上的数据远高于平均值
group by维度过小,某值的数量过多某个维度或者某几个维度且这些维度的数据量特别大,集中在一个reduce

5、数据倾斜的解决方案

5.1、特殊情形处理

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

  • 情形:比如用户表中user_id字段为int,log表中user_id字段string类型。当按照user_id进行两个表的Join操作时。

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

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

②null key不参与关联

select
	a.*
from(
    select
	    *
	from log
    where user_id is not null
	 ) a
	join
	users b on a.user_id = b.user_id
	union all
	select
	*
	from log where user_id is null

③数据加盐:赋予null值随机值

1. select *
2. from log a
3. left outer join users b
4. 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 job数是1 ;
	这个优化适合无效 id (比如 -99 , ’’, null 等) 产生的倾斜问题。
	把空值的 key 变成一个字符串加上随机数,就能把倾斜的数据分到不同的reduce上 ,解决数据倾斜问题。

④提高reduce并行度

设置reduce个数:set mapred.reduce.tasks=15,可以通过改参数提高reduce端并行度,从而缓解数据倾斜的情况。

1>未优化前,假设key1、key2、key3、key4的数据量都是50w,key5是10w,此时key1和key3shuffle到了一个reduce,key2和key4shuffle到了一个reduce,导致有两个reduce task需要处理100w数据,而有一个task只需要处理10w数据,此时数据出现了10倍的倾斜。

在这里插入图片描述
2>优化后,如图所示,为优化前reduce的并行度为3,单个task处理的最大数据量为100w,现在将并行度提高到5,单个task处理的最大数据量为50w,相比之前缓解了5倍的倾斜程度。此方案适合倾斜的程度不是很严重,并有两个以上的倾斜key到shuffle到了同一个reduce。
在这里插入图片描述

5.2、group by导致的数据倾斜

①开启负载均衡

②group by 双重聚合

当使用group by进行聚合统计时,如果存在某个或某几个key发生了倾斜,会导致某个倾斜key shuffle到一个reduce。
在这里插入图片描述

select
    split(sp_app_id,'_')[0] sp_app_id
   ,sum(pv)
from
(
	select
    sp_app_id||'_'||CAST(CAST(MOD(rand() * 10000,10) AS BIGINT) AS STRING) sp_app_id
    ,sum(nvl(op_cnt, 1)) pv
	from t1
   group by sp_app_id||'_'||CAST(CAST(MOD(rand() * 10000,10) AS BIGINT) AS STRING)
) group by split(sp_app_id,'_')[0]
5.3、join导致的数据倾斜

reduce join 转换成 map join(此方案适合小表join大表的时候)

select /*+ mapjoin(t2)*/ column from table

②过滤倾斜join单独进行join

所以如果把倾斜key过滤出来单独去join,这个倾斜key就会分散到多个task去进行join操作,最后union all。
在这里插入图片描述

select
    *
from
(
    select
        *
    from t1
    where rowkey <> '123456789'
) a1 join a2 on a1.rowkey = a2.rowkey
union all
select
    *
from
(
    select
        *
    from t1
    where rowkey = '123456789'
)a1 join a2 on a1.rowkey = a2.rowkey
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随缘清风殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值