美文网首页
SQL篇—Hive数据倾斜(二)

SQL篇—Hive数据倾斜(二)

作者: 年少轻狂不能用来挥霍 | 来源:发表于2019-03-29 09:17 被阅读0次

    这是面试经常遇到的问题,虽然我还没有机会在实战中面对过。

    • 1.参考文章:
      Hive的数据倾斜:
      https://www.cnblogs.com/qingyunzong/p/8847597.html

      https://www.cnblogs.com/kongcong/p/7777092.html
      https://www.jianshu.com/p/ab08de658adc

    • 2.表现:进度卡在99%,某一个reduce子任务总比其他时间长

    • 3.易出现数据倾斜的情况
      a. join: 其中一个表小,但key集中/分桶的判断字段0值或空值较多
      b.group by: 维度过小,某值的数量过多
      c. count distinct: 某特殊值过多

    • 4.原因:
      key分布不均
      建表时考虑不周
      业务数据本身特性
      某些SQL本身

    • 5.solution:
      a.表小但key集中
      产生新的key,对应的数据分布尽可能均匀

      map join:将其中做连接的小表(全量数据)分发到所有 MapTask 端进行 Join,从而避免reduceTask,前提要求是内存足以装下该全量数据
      用法:在select后面添加/* +mapjoin(tablelist)*/提示优化器转化为map join ,通常tablelist是小表,全量发送到内存

      select /* +mapjoin(a) */ a.id aid, name, age from a join b on a.id = b.id;
      

      Hive0.11版本以后会自动开启mapjoin优化,由两个参数设置:
      set hive.auto.convert.join=true; //设置 MapJoin 优化自动开启
      set hive.mapjoin.smalltable.filesize=25000000 //设置小表不超过多大时开启 mapjoin 优化

      但如果小表太大,无法全量发送,那么需要对上述方法进行改进。
      如日志表和用户表的连接:

      select * from log a left outer join users b on a.user_id = b.user_id;
      

      相对于log,user表是小表但量很大,改进:

      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 = x.user_id;
      

      b.空值较多
      将空值的key变成字符串+随机数

      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;
      

      c.不同数据类型关联
      user表中 user_id 字段为 int,log 表中 user_id 为既有 string 也有 int 的类型, 进行 join 操作的时候,默认的 hash 操作会按照 int 类型的 id 进 行分配,这样就会导致所有的 string 类型的 id 就被分到同一个 reducer 当中

      select * from user a left outer join log b on b.user_id = cast(a.user_id as string)
      

    相关文章

      网友评论

          本文标题:SQL篇—Hive数据倾斜(二)

          本文链接:https://www.haomeiwen.com/subject/irycbqtx.html