Hadoop MapReduce/Hive 数据倾斜完整排查

数据倾斜本质:Shuffle 阶段,某一个 / 某几个 Reduce 接收的数据量远大于其他 Reduce,任务长时间卡在这几个 Reduce,出现长尾任务,严重时 OOM。

一、现象识别(怎么判断发生倾斜)

现象 1:YARN 页面观察

  1. 大部分 Reduce 任务快速跑完,少数几个 Reduce 进度卡在 99%、100% 很久不动,耗时远高于其余 task。
  2. 看 Counters → Reduce input records 计数器:
    • 绝大多数 reduce 输入记录数几万,个别 reduce 几百万、上千万条,数量差距几十上百倍。

✔ Counter 只能确认倾斜发生,看不到具体热点 key。

现象 2:日志异常

  • 慢 Reduce 的 Container 日志:频繁 Full GC、OOM、内存溢出报错。
  • Task 日志大量重复相同 key。

现象 3:Hive SQL 表现

  • Map 阶段很快结束,MR Job 卡在 Reduce 阶段,任务跑很久不结束。

二、完整排查步骤

  1. 确认是否发生数据倾斜 :YARN UI 打开对应 Job → Counters 标签,查看 Reduce input records。如果个别 reduce 输入记录数远超其他,确认倾斜。

  2. 定位出有问题的 Reduce Task:进入 Job 的 Attempts/Container 列表,找到执行时间极长、进度停滞的 Reduce 任务,复制该 Container ID。

  3. 下载该 Reduce Task 日志,定位热点 Key :打开该 container 日志,搜索 key 相关打印,找到数量爆炸的热点 key 具体值。

    注意:MR 原生计数器不保存 key,日志才能拿到真实 key。

  4. 分析倾斜产生的根因 :拿到热点 key 后分析业务:

    • 大量 null、空字符串 key;
    • 某个业务 key 数据量异常大;
    • join 的一侧存在大量重复 key;
    • 分区函数不合理。
  5. 区分倾斜类型 :

    • ✅ Group By / 聚合倾斜:group by 的某个 key 值数据量巨大
    • ✅ Join 倾斜:join 的其中一张表有大量重复 join key
    • ✅ Count Distinct 倾斜:去重,相同 key 过多

三、常见倾斜分类 + Hive 解决方案

类型 1:group by 数据倾斜(聚合倾斜)

场景:group by 某个字段,某个 key 行数特别多。现象:reduce 输入记录数严重不均。

优化方案

  1. 开启 map 端预聚合

    set hive.map.aggr=true; --map端局部聚合
    set hive.groupby.mapaggr.checkinterval=100000;

  2. 开启倾斜自动处理

    set hive.groupby.skewindata=true;

原理:拆两轮 MR。第一轮随机打散做局部聚合;第二轮再汇总。代价:多一轮 MR,消耗资源。

类型 2:Join 数据倾斜

场景:大表 join 大表,join key 存在热点;或者大表 join 小表但 key 热点。

方案 A:小表侧 mapjoin(小表全部加载到 map 内存,无 shuffle,不走 reduce join)

复制代码
set hive.auto.convert.join=true;
set hive.mapjoin.smalltable.filesize=25000000;

适用:一张表很小,另一张大表。

方案 B:热点 key 打散(大表 join 大表,存在热点 key)

思路:

  • 对大表热点 key,拼接随机前缀打散,分到不同 reduce;
  • 另外一张表,把热点 key 复制 N 份,带上对应随机前缀;再做 join。

适合:join 的热点 key 只是少数,其他 key 正常。

方案 C:分离热点 key 单独处理

把热点 key 过滤出来单独做 join;非热点 key 正常 join;最后把两部分结果 union all 合并。

类型 3:null / 空值 key 导致倾斜

场景:大量记录 join/group by 的 key 为 null、空字符串,全部 hash 到同一个 reduce。优化:

  1. 过滤掉 null(业务允许情况下);

  2. null 值给随机前缀打散,不让全部落到同一个 reduce。

    -- 示例,null打上随机数
    case when key is null then concat('rand_',rand()) else key end as join_key

类型 4:count distinct 去重倾斜

count (distinct id),同一个 id 数量巨大,shuffle 全部落到同一个 reduce。优化:先 group by 去重,再 count。

复制代码
--倾斜写法
select count(distinct id) from table;

--优化改写
select count(*) from (select id from table group by id) t;

四、参数

复制代码
--开启mapjoin
set hive.auto.convert.join=true;
--groupby倾斜优化
set hive.groupby.skewindata=true;
--map端聚合
set hive.map.aggr=true;
--倾斜join自动优化(hive新版本)
set hive.optimize.skewjoin=true;
set hive.skewjoin.key=100000;

五、精简版

排查数据倾斜,首先看 YARN 任务 Counter 中 Reduce-input-records,观察每个 reduce 输入数据量,如果少数 reduce 数据量远大于其他,确认发生数据倾斜。然后找到耗时很长的那个 reduce 对应的 Container,下载 task 日志,从中定位热点 key。

倾斜主要分 groupby 聚合倾斜、join 倾斜、null 值倾斜、count distinct 倾斜。优化手段有 map 端预聚合、skewindata 开启两轮 MR、mapjoin、热点 key 打散、分离热点单独处理、改写 count distinct。

六、容易踩考点

  1. Counter 只能发现倾斜,不能直接看到热点 key,热点 key 要去 container 日志找。
  2. 数据倾斜发生在Shuffle 阶段。
  3. hive.groupby.skewindata=true 会把 group by 拆两轮 MR,会增加任务耗时,不要无脑开启。
  4. mapjoin 没有 shuffle 阶段,完全规避 join 倾斜,但受内存限制,只适合小表。
相关推荐
freejackman1 天前
【工程化】从“单兵作战”到“多引擎架构”:基于门面模式的重构实战
大数据·数据库·hive·sql·测试工具·设计模式·架构
skywalk81634 天前
hive 常驻集群:像 OSPF 一样在线,像 git 一样可信
运维·人工智能·hive
Francek Chen5 天前
【大数据处理与分析】数据仓库Hive:09 Hive 编程实践
大数据·数据仓库·hive·hadoop·sql
茶海棠8 天前
Hadoop+zookeeper+HBase+Kafka集群搭建全流程
hadoop·zookeeper·kafka·hbase
skywalk81638 天前
卡不等于分支:我用 TRAE 宝配合 Hive 跑三张任务卡的一天
运维·人工智能·hive·trae
freejackman9 天前
【架构篇】双遍历 + 多栈协同:手撸 SQL 血缘引擎的架构思考
java·大数据·数据库·hive·sql·架构·spark
陈年老古董9 天前
ClickHouse 单机搭建记录
hive·笔记·学习·clickhouse·硬件架构
Gl�ria9 天前
Hadoop 速刷:HDFS / MR / YARN / Spark / Hive
hadoop·hdfs·mr
陈年老古董9 天前
Spark 3.1.3 集群搭建 + Spark-SQL 整合 Hive 记录
hive·sql·spark
FserSuN9 天前
Hive 分区表存储与查询优化学习总结
hive·hadoop·学习