Hive的数据倾斜问题

hive的数据倾斜

一、现象

作业已经完成了99%,就剩下1%,结果跑了很久,这大概率就是出现了数据倾斜。

二、原因

  1. key值分布不均匀
  2. 数据本身分布不均
  3. 某些sql写的有问题
  4. 建表的时候考虑不周

三、解决方法

  1. 利用参数调节

    • hive.map.aggr = true , map端部分聚合,相当于combiner

    • hive.groupby.skewindata=true

      当有数据倾斜发生的时候,会执行两个mr任务。第一个阶段,map会将数据随机发送到reduce中,每个reduce做部分的聚合操作,这样可以保证结果是均衡的。第二阶段,map会根据group by key将key相同的数据发送到同一个reduce中,保证结果的正确性。

  2. SQL语句调节

    • join语句
      • 选取key分布表均匀的数据表作为驱动表
      • 做好列裁切和filter操作,达到两表join后数据量相对变小的效果。
      • 大小表join时,利用map join,将小表加载进内存,省略reduce阶段
      • 大表join大表的时候,对于空值key,可以采用赋随机值的方法,分散到不同的reduce上。(因为key值为空,最后肯定也匹配不上,所以不影响)
    • count distinct
      • 如果仅仅只是计算count distinct,可以直接将key为空的过滤掉。
      • 如果还有其他运算,则需要group by,然后将key为空的值进行处理,最后union回去。
    • group by维度过小 (换句话说,也可以理解为数据值重复的很少。)
      • 用 sum() group by 的方式替换 count( distinct )完成计算。
  3. 如果用sql语句的优化效果不好的话,可以直接将倾斜的数据单独拎出来进行分析。

四、场景

  1. 空值产生的数据倾斜
    • 方法一:将key为null的值过滤掉
    • 方法二:给key为null的值随机赋值
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;
select *
  from log a
  left outer join users b
  on case when a.user_id is null then concat(‘hive’,rand() ) else a.user_id end = b.user_id;
  1. 不同数据类型之间的关联,产生的数据倾斜

    • 比如int类型和string类型进行关联,默认的hash会按照int型的id进行分配,这样所有的string类型值都会分配到同一个reduce中。

      解决方法:

      将int型数据改为string型。

  2. 小表不够小,无法加入到内存中,不能map join

    select * from log a
      left outer join users b
      on a.user_id = b.user_id;
    
    select /*+mapjoin(x)*/* from log a
      left outer join (
        select  /*+mapjoin(c)*/d.*
          from ( select distinct user_id from log ) c
          join users d
          on c.user_id = d.user_id
        ) x
      on a.user_id = b.user_id;	
    

    第一段代码就会因为log日志过大无法加载到内存中而报错,第二段代码是一种优化。利用user_id将数据进行分割。

    这个方法有个前提就是,user表中的数据量不是特别大,如果有上百万个user_id,那第二段代码和第一段代码其实就没有太大的区别了。

    但是一般来说,每日的会员uv不会太多,有交易的会员也不会太多,有点击的会员也不会太多,有佣金的会员也不会太多。所以这个方法能解决大部分的数据亲些问题。

五、总结

要解决数据倾斜的问题,归根结底是要想办法将map的输出尽可能均匀的分配到reduce中去。大部分的数据倾斜都是由于建表疏忽或者通过业务逻辑可以直接规避掉的。

  1. 对于小表小于1G的情况下,采用map Join。
  2. 对于group by或者distinct 设置 hive.groupby.skewindata=true;
  3. 尽量使用上述sql语句进行调节优化。

参考文章:
数据倾斜整理(转)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值