当前位置: > > > Hive - 数据倾斜的原因以及解决办法(附样例)

Hive - 数据倾斜的原因以及解决办法(附样例)

    在大数据处理的过程中,Hive 是一种常用的工具。然而,在处理大规模数据时,数据倾斜问题往往会导致查询性能下降,甚至查询失败。本文将介绍 Hive 数据倾斜的原因,并提供几种有效的解决方案。

一、数据倾斜原因分析

1,可能会触发 Hive 数据倾斜的情况

关键字 情形 后果
join 大表与小表,小表中的 key 集比较集中 分发到某一个或几个 Reduce 上的数据远高于平均值
join 大表与大表,但是 join 中指定的字段 0 值或空值过多 这些空值都由一个 reduce 处理,非常慢
group by group by 维度过小,处理的数量过多 处理某值的 reduce 非常耗时

2,造成数据倾斜的原因

(1)key 分布不均匀
(2)业务数据本身的特性
(3)建表时考虑不周
(4)某些 SQL 语句本身就有数据倾斜

3,数据倾斜的表现

(1)任务进度长时间维持在 99%(或 100%),查看任务监控页面,发现只有少量(1 个或几个)reduce 子任务未完成。因为其处理的数据量和其他 reduce 差异过大。
(2)单一 reduce 的记录数与平均记录数差异过大,通常可能达到 3 倍甚至更多。 最长时长远大于平均时长。

二、数据倾斜的解决方案

1,调整 Hive 配置

(1)hive.map.aggr 参数用于在 Map 阶段进行部分聚合,可以有效地减少需要传输到 Reduce 阶段的数据量,从而减轻 Reduce 阶段的负担。
SET hive.map.aggr=true;

(2)hive.groupby.skewindata 参数参数设置为 true 时,Hive 会在执行 Group By 操作时检测并处理数据倾斜。具体来说其生成的查询计划会有两个 MR Job
  • 第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;
  • 第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。
SET hive.groupby.skewindata=true;

2,SQL 语句调节

(1)针对大小表 Join
  • 使用 map join 让小的维度表(1000 条以下的记录条数) 先进内存,在 map 端完成 join 操作。正常情况下 join 是需要在 reduce 端执行的,通过 map join 可以实现在 map 端执行 join 操作,这样可以避免在 shuffle 的时候造成数据倾斜。

(2)针对大表 Join 大表:
  • 把空值的 key 变成一个字符串加上随机数,把倾斜的数据分到不同的 reduce 上,由于 null 值关联不上,处理后并不影响最终结果。

(3)优化 Group By 操作:
  • 下面 SQL 其实是一个解决数据倾斜的 SQL(添加随机数,两阶段聚合)。先看里面的 select 语句,里面的 select 语句其实是根据 key 进行分组,但是这个 key 对应的数据存在数据倾斜,key=KEY001 的数据占了整份数据的 90%,所以直接针对 key 进行分组肯定会出现数据倾斜,应该计算效率,所以在这里就实现了曲线救国,先把 key=KEY001 的数据打散,分成 50 份,进行局部聚合。最后再通过外面的 select 进行全局的聚合,这样就可以显著提高计算效率。
SELECT a.Key
    , SUM(a.Cnt) AS Cnt
FROM (
    SELECT Key
        , COUNT(*) AS Cnt
    FROM TableName
    GROUP BY Key,
        CASE
            WHEN Key = 'KEY001' THEN Hash(Random()) % 50
            ELSE 0
        END
) a
GROUP BY a.Key;
评论0