Hive数据倾斜方案

数据倾斜:
数据倾斜通常发生在 MapReduce 框架中,通俗理解就是在整个计算过程中,大量相同的 key 被分配到同一个任务上,导致大部分任务空闲,个别任务一直运算,使得计算效率很低。

MapReduce 执行原理:

  • Map 任务
  • MapReduce 读取 HDFS 中的文件并进行切割,将每行解析成一个
    Map 任务将上一步生成的 值转换成新的 ,并将结果写入到环形缓冲内存中(溢出的部分写入磁盘)。
    Map 任务将不同分区中的数据进行排序、分组,将相同的 k 放入同一个集合中(溢出的部分写入磁盘)。
    Map 对分组后的任务进行归约。

  • Reduce 任务
  • Reduce 任务先处理多个 Map 任务的输出结果,再根据分区将其分配到不同的 Reduce 节点上(shuffle)。
    Reduce 对多个 Map 的输出结果进行合并、排序、计算,重新生成新的 值。
    Reduce 将上一步生成的 值写入到 HDFS 中,生成文件。

解决方案:
日常工作中产生的数据倾斜多产生于 Reduce 阶段,其原因在于没有考虑到某种 key 值数据过多而导致的。而最容易产生数据倾斜的场景:
  • Join 倾斜
  • Count Distinct
  • GROUP BY 倾斜
  • 1. 加盐
  • 对倾斜Key添加随机前缀/后缀,将单一Key分散为多个子Key,分散计算压力。首先对key 添加随机数,之后再去除随机数进行聚合。

  • 2. 两阶段聚合
  • 将聚合拆分为局部聚合(分散计算)和全局聚合(合并结果),减少单个节点负载。 在对key 进行group by 时,添加随机数分散数据,之后再进行汇总。

  • 3. MapJoin处理小表倾斜
  • 将小表加载到内存,避免Shuffle 阶段的数据倾斜。 设置 SET hive.mapjoin.smalltable.filesize=25000000; 参数,将小表加载到内存中。

  • 4. MapJoin优化
  • 设置参数 set hive.map.aggr = true; set hive.groupby.skewindata = true;
    将上述两个参数设置为 true 后,MapReduce 进程会生成两个额外的 MR Job,这两个任务的主要操作如下:
    MR Job 中的 Map 输出结果集合首先会随机分配到 Reduce 中,然后每个 Reduce 做局部聚合操作并输出结果(相同的 Group By Key 可能会被送到不同的 Reduce Job 中)。
    MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(相同的 Group By Key 会被送到相同的 Reduce Job 中),最后完成聚合操作。

  • 5. SQL 优化
总结:
  • 如果任务长时间卡顿在 99%,那大概率发生了数据倾斜。
  • 小表关联大表,需要先看能够使用子查询,再看能否使用 Mapjoin。
  • Join 操作注意关联字段不要出现大量的重复值或空值。
  • Count(Distinct id) 去重统计慎重使用,尽量通过其他方式替换。
  • Group by id 添加随机数,多阶段聚合处理。