聊一聊hive数据倾斜

info基本信息表
user_idnameagegender
1henry16
2jack17
3anny18
4candy19
5kate20
 burke21 
 frank22 
 ellen23 
 ken24 
 mili25 
............
score成绩表
user_idsubject_idscore
1189
1290
1391
4292
4393
6194
7395
8196
8297
8398
.........

一、何为hive数据倾斜?

是因为数据分布的不均匀,导致一大部分数据集中到某一个节点上,其他数据少的节点早早的就完成了计算任务,数据量大的节点还在计算中,使得整个job进度长时间停留在 map100%,reduce99%,这就是因为数据发生了倾斜导致的结果。

导致数据倾斜有以下原因:

1.数据本身某个key值较多,导致分布不均,比如说上述info表中性别一列只有两个男生,两个女生,其余为空值。这样大量的空值字段会导致数据倾斜。

2.针对某个业务,导致某个key值较多,分布不均匀,比如说group by时某个字段值较多。比如说上述info表中男生数量只有几个,其余皆为女生。如果要按照性别分组,这样极易导致倾斜。

3.建表时考虑不周全

4.某些hql语句本身就有数据倾斜。

二、如何解决数据倾斜?

1.若数据中某个字段有大量空值,存在信息缺失的情况。导致在表之间进行关联时,发生数据倾斜。

比如,将info表和score表关联,那么info表中的user_id字段存在大量空值,会导致数据倾斜。

解决办法:要么先将空值过滤掉,最后再将空值union all进去。

select *
from info a
join score b
on a.user_id is not null and a.user_id=b.user_id
union all
select * from info c where c.user_id is null;

要么将空值分配一个字符串+随机数。

select *
from info a
left join score b
on
case when a.user_id is null then concat(hive,rand()) else a.user_id end =b.user_id;

第二种执行效率会更高一些,因为第一种会读两次表。而第二种只读一次表,且由于null值关联不上,处理后并不影响最终结果。

2.若两张表中在做join时,相关联的字段的数据类型不一致时会导致数据倾斜。

如果info表中user_id的属性是int,score表中user_id的属性是string,在做两表关联时,容易发生数据倾斜。

解决办法:将数据类型转成一致的类型,使用cast函数。

select *
from info a
left outer join score b
on b.user_id = cast(a.user_id as int)

3.当大小表关联查询时会发生数据倾斜。

解决办法:在map端完成join。这里是inner join。将小表加载到内存中,使得每个map task上都有此小表,小表分别和各个数据块做join。在hive的0.11版本后,会自动开启map join优化,具体参数设置如下:

set hive.auto.convert.join=true;(默认开启)
set hive.mapjoin.smalltable.filesize=25000000;//设置小表的大小,不超过则开启mapjoin

4.当大表和大表相关联时发生数据倾斜。

解决办法:将大表1中关联列去重后单独抽出,形成一张小表。将此小表和大表2先关联,关联好后再和大表1进行关联。

 

5.当对表中数据做一些类型统计的时候遇到过某种类型的数据量特别多,而其他类型数据的数据量特别少。当按照类型进行 group by 的时候,会将相同的 group by 字段的 reduce 任务需要的数据拉取到同一个节点进行聚合。比如说计算info表中男女生数量。(比如男生很少,女生很多)

解决办法:开启 Map 端聚合参数设置

//是否在 Map 端进行聚合,默认为 True
set hive.map.aggr = true;
//在 Map 端进行聚合操作的条目数目
set hive.groupby.mapaggr.checkinterval = 100000;
//有数据倾斜的时候进行负载均衡(默认是 false)
set hive.groupby.skewindata = true;
当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job中,Map 的输出结果会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并 输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到 同一个 Reduce 中),最后完成最终的聚合操作。

6.当hql语句中包含 count(distinct)时,如果数据量非常大,查询各个学生考了几门课程的考试。执行如 select user_id,count(distinct subject_id) from score group by score;类型的 SQL 时,会出现数据倾斜的问题。

解决办法:使用sum...group by 代替

select
user_id,sum(1)
from 
(
    select user_id,subject_id from score group by user_id,subject_id
)
group by user_id;

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值