数据倾斜

来自牛奶河Wiki
跳到导航 跳到搜索

数据倾斜:在并行进行数据处理的时候,由于单个 partition 的数据显著多余其他部分,分布不均匀,导致大量数据集中分布到少数计算节点上,使得该部分的处理速度远低于平均计算速度,成为整个数据集处理的瓶颈,从而影响整体计算性能。

原因

  1. 对于 join 过程来说,如果出项较多的 key 值为空或异常的记录,或 key 值分布不均匀,就容易出现数据倾斜
  2. 对于 group by 过程来说,如果某一个 key 值有特别的多的记录,其它 key 值的记录比较少,也容易出项数据倾斜

方案

Join

  1. 如果是由于 key 值为空或为异常记录,且这些记录不能被过滤掉的情况下,可以考虑给 key 赋一个随机值,将这些值分散到不同的 reduce 进行处理
  2. 如果是一个大表和一个小表 join 的话,可以考虑使用 mapjoin 来避免数据倾斜

Group

方法一:

set hive.groupby.skewindata=true

只针对单列有效。数据倾斜时负载均衡,当选项设定为 true,生成的查询计划会有两个 MRJob。第一个 MRJob 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MRJob 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

方法二:

set hive.map.aggr=true;

在 map 中会做部分聚集操作,效率更高但需要更多的内存。开启 map 之后使用 combiner,这样基本上是对各记录比较同质的数据效果比较好,相反,则没有什么意义。通用的做法是设置下面两个参数:

set hive.groupby.mapaggr.checkinterval = 100000     # (默认)执行聚合的条数
set hive.map.aggr.hash.min.reduction=0.5            # (默认)
  1. 如果 hash 表的容量与输入行数之比超过这个数,那么 map 端的 hash 聚合将被关闭,默认是 0.5
  2. 设置为 1 可以保证 hash 聚合永不被关闭