Hive--数据倾斜以及解决方案

数据倾斜

一:什么是数据倾斜?

​ 由于数据分布不均匀,造成数据大量的集中到一点,造成数据热点 ,简单来说就是大量相同的key被partition到同一个分区里面导致某些或者某个reducetask压力过大,而一些reducetask闲住。这样也违背了并行计算的初衷。

二:数据倾斜的主要表现?

​ 任务进度长时间维持在 99%或者 100%的附近,查看任务监控页面,发现只有少量 reduce 子任务未完成,因为其处理的数据量和其他的 reduce 差异过大。 单一 reduce 处理的记录数和平均记录数相差太大,通常达到好几倍之多,最长时间远大 于平均时长。

三:不容易产生数据倾斜的情况?

1)聚合函数 和 group by 一起使用的时候 ,在map端默认执行执行 combiner ,combiner是在map阶段,reduce之前的一个中间阶段,在这个阶段可以选择性的把大量的相同key数据先进行一个合并,可以看做是local reduce,然后再交给reduce来处理,这样做的好处很多,即减轻了map端向reduce端发送的数据量(减轻了网络带宽),也减轻了map端和reduce端中间的shuffle阶段的数据拉取数量(本地化磁盘IO速率),

2)只有map操作的时候,map中的key是唯一的,就不会存在很多相同的key被partiton到同一个分区;

3)某些查询hql语句 不会转换为mr
select * from stu_managed01
select * from stu_managed01 where age>19
select * from stu_managed01 where age>19 limit 3
select sid,name from stu_managed01 limit 10;

hive fetch 抓取  流  读取hdfs的数据的时候没有mr的参与:
通过命令行设置set hive.fetch.task.conversion=
    1.none  这个参数禁用    所有的操作都没有fetch  都要转换为mr      
    2.minimal  SELECT *, FILTER on partition columns (WHERE and HAVING clauses), LIMIT only
        1)select * 
        2) where 是分区字段
        3)limit 
    3.more  SELECT, FILTER, LIMIT only (including TABLESAMPLE, virtual columns)
        1)select 表任何原生字段
        2)where 
        3)limit 
        group by   order by   distinct  聚合  mr 
四:哪些场景容易产生数据倾斜?
  1. group by不和聚合函数一起使用的时候;
  2. count(distinct),在数据量大的情况下,容易数据倾斜,因为 count(distinct)是按 group by 字段分组,按 distinct 字段排序;
  3. 小表关联超大表 join
五:产生数据倾斜的原因?
  • key 分布不均匀
  • 业务数据本身的特性
  • 建表考虑不周全
  • 某些 HQL 语句本身就存在数据倾斜
六:数据倾斜的具体场景分析?
1)表连接的关联建存在大量空值

原因:

一旦关联键存在大量空值,在reduce的时候,大量null会被分配到一个redecetask中,可以去除null值,但是这就需要判断和解决null的问题,这需要计算,无疑增大了某一reducetask的压力,从而造成数据倾斜

解决方案:

  1null值不参与连接
    select 
    *
    from user a 
    join (
    select * from log where userid is not null 
    ) b on a.userid=b.userid 
    union 
    select null,null,null,* from log where userid is null;
 2)null值加随机数,这样null就不会都被分到一个reducetask中
  select * from log a left outer join user b on
  case when a.user_id is null then concat('hive',rand())     else a.user_id end = b.user_id;
2)关联键字段类型不一致

原因:

例如两个表连接,关联字段一个是int类型一个是string类型,会强制将string类型转换为int类型,但是有的转换不了,这样就会转化为空值,又变成了大量空值造成数据倾斜

解决方案:

将字段类型统一
select * from user a left outer join log b on b.user_id = cast(a.user_id as string);
3)大小表关联产生数据倾斜

这里怎么理解大表还是小表:hive.mapjoin.smalltable.filesize=25000000//23.8M系统默认的小表大小,因为表的大小于23.8M,join就是mapjoin,一旦表的大小超过23.8M就是reducejoin;

①小表和大表连接

当小表的大小下雨23.8M的时候,join执行的是mapjoin,不会产生数据倾斜;

②中表和大表连接

当一张表的大小超过23.8M,但是数据量不是特别大的时候,可以称之为中表,这时候如果硬件物理内存足够,可以强制进行mapjoin,这样就可以避免数据倾斜

MapJoin 具体用法:
select /* +mapjoin(a) */ a.id aid, name, age from a join b on a.id = b.id;
select /* +mapjoin(movies) */ a.title, b.rating from movies a join ratings b on a.movieid = 
b.movieid;

还可以通过hive参数的配置来解决什么时候是mapjoin

set hive.auto.convert.join=true;
//设置 MapJoin 优化自动开启
set hive.mapjoin.smalltable.filesize=25000000
//设置小表不超过多大时开启 mapjoin 优化

③大表和大表连接

解决方式一:

将两个大表切分为小表,分别再mapjoin;

解决方式二:

瘦身,通过过滤掉表中业务需求用不到的东西从而达到瘦身的目的;

例如:有日志表log和用户表user;其中要查询活跃的用户的日志信息,可以通过日志表达到对用户表的过滤,有日志信息的用户才是活跃用户;

①求出log表中的独立用户
select distinct user_id 
from log;
②对user表进行过滤,只要log表中存在的用户
select /*+mapjoin(b)*/   a* 
from user a join 
(select distinct user_id 
from log)b on 
a.user_id =b.user_id;
③真正的连接
select * 
from 
(select /*+mapjoin(b)*/   a* 
from user a join 
(select distinct user_id 
from log)b on 
a.user_id =b.user_id) c join log d on c.user_id=d.user_id;
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值