3. 数据倾斜诊断工具

做数据倾斜调优,最怕什么?

不是问题有多复杂,而是你连「到底哪里倾斜了」都看不出来。

我见过不少团队,一遇到任务慢就盲目加资源,结果 Spark 的 Executor 从 10 个加到 100 个,倾斜的 Task 还是跑 2 小时。说白了,工具就在手边,但很多人没看懂它给的信号。

这一章,我就带你把这三大诊断工具吃透:Spark UI、Hive Explain、Flink Web Dashboard。每个工具我都会结合真实踩坑经历来讲,保证你学完就能用。

核心观点:诊断工具是你的「眼睛」。学会看,比学会调更重要。调优 80% 的时间应该花在诊断上,而不是盲目改代码。

数据倾斜诊断工具知识体系 数据倾斜诊断工具全景图 Spark UI Hive Explain Flink Web Dashboard Stage 页 Task 页 Shuffle Read/Write STAGE DEPENDENCIES Map/Reduce 算子 数据倾斜标记 SubTask 指标 Watermark 延迟 反压监控 诊断铁三角:看 Stage → 查 Task → 盯 Shuffle Hive 看计划,Flink 看反压,Spark 看数据分布

3.1 Spark UI:Stage、Task、Shuffle 三页定乾坤

Spark UI 是我用得最多的诊断工具,没有之一。它把一次作业的执行过程拆成了三个关键页面,你只要盯住这三个地方,倾斜问题基本无所遁形。

3.1.1 Stage 页面:一眼看出「谁在拖后腿」

打开 Spark UI,先看 Stages 标签页。这里列出了所有 Stage,每个 Stage 后面有个「Duration」列。

正常情况,所有 Stage 的耗时应该差不多。如果某个 Stage 的耗时是其他 Stage 的 5 倍甚至 10 倍,那基本可以断定——这个 Stage 内部发生了数据倾斜。

我的经验:有一次我优化一个 ETL 任务,发现 Stage 3 跑了 45 分钟,而其他 Stage 平均只要 3 分钟。点进去一看,Shuffle Read 阶段有 3 个 Task 各读了 2GB 数据,其余 Task 只读了 50MB。这就是典型的「长尾效应」——少数 Task 撑起了整个 Stage 的耗时。

3.1.2 Task 页面:数据分布一目了然

点进有问题的 Stage,你会看到 Tasks 列表。这里有两个关键指标:

  • Shuffle Read Size / Records:每个 Task 读取的数据量。如果最大值和最小值相差超过 3 倍,就要警惕了。
  • Duration:每个 Task 的执行时间。倾斜的 Task 通常耗时是平均值的 5 倍以上。

我习惯按「Shuffle Read Size」降序排列,一眼就能看到「数据胖子」是谁。你想想看,如果 100 个 Task 里,有 3 个 Task 各读了 1GB,其余 97 个只读了几十 MB,这不就是典型的 Key 分布不均吗?

注意:不要只看 Duration。有时候 Task 跑得慢不是因为数据量大,而是因为 GC 频繁或资源竞争。一定要结合 Shuffle Read Size 一起看,才能准确定位。

3.1.3 Shuffle Read/Write:倾斜的「照妖镜」

Shuffle 阶段是数据倾斜的高发区。在 Spark UI 的 Stages 页面,每个 Stage 都有「Shuffle Read」和「Shuffle Write」两个指标。

指标 正常值 倾斜信号
Shuffle Write (单个 Task) < 200 MB > 500 MB,且与其他 Task 差距大
Shuffle Read (单个 Task) < 300 MB > 1 GB,且出现长尾
Shuffle Spill (磁盘溢出) 0 或很小 大量 Spill,说明内存不够或数据倾斜

我曾经遇到一个案例:Shuffle Write 阶段,某个 Task 写了 2.5GB 数据到磁盘,而其他 Task 平均只写了 100MB。点进去一看,这个 Task 处理的 Key 是空字符串——因为上游数据清洗没做,大量空值被 group by 到了同一个分区。这就是典型的「空值倾斜」。

3.2 Hive Explain:执行计划的「X 光机」

Hive 的 EXPLAIN 命令,很多人觉得它晦涩难懂,就跳过了。但我告诉你,这是诊断 Hive 数据倾斜最直接的武器。

3.2.1 怎么看懂执行计划

在 Hive CLI 或 Beeline 里执行:

EXPLAIN EXTENDED SELECT key, COUNT(*) FROM table GROUP BY key;

输出会包含三大部分:

  • STAGE DEPENDENCIES:Stage 之间的依赖关系,告诉你哪些 Stage 可以并行,哪些必须串行。
  • STAGE PLANS:每个 Stage 内部的算子细节,包括 Map 操作、Reduce 操作、Join 类型等。
  • Statistics:Hive 预估的输入输出数据量,如果预估偏差很大,说明统计信息不准。

关键点:在 STAGE PLANS 里,找到 Reducer 或 Map Join 相关的算子。如果看到 Group By Operator 后面跟着 mode=mergepartial,说明 Hive 在做两阶段聚合——这是 Hive 自动优化的倾斜处理策略。

3.2.2 如何从计划中识别倾斜风险

我总结了一个「三步看计划」的方法:

  1. 看 Join 类型:如果 EXPLAIN 输出里是 Map Join,一般不会倾斜;如果是 Reduce Side Join 或 Common Join,就要小心了——所有数据都要经过 Shuffle。
  2. 看 Reducer 数量:Hive 会根据数据量估算 Reducer 数。如果 Reducer 数很少(比如只有 1 个),而数据量很大,那这个 Reducer 就是「单点瓶颈」。
  3. 看数据倾斜标记:在 EXPLAIN EXTENDED 的输出里,有时会出现 SKEW 或 skewed 字样,这是 Hive 在告诉你:「嘿,这里的数据分布可能有问题!」

避坑指南:我曾经遇到一个 SQL,EXPLAIN 显示 Reducer 数为 1,但数据量有 10 亿行。我以为是 Hive 统计信息不准,手动设置了 mapred.reduce.tasks=100。结果跑完一看,还是只有一个 Reducer 在干活——因为 GROUP BY 的 Key 只有 3 个唯一值,Hive 强制把所有数据路由到了 3 个 Reducer 上,而其中一个 Reducer 处理了 80% 的数据。所以,Reducer 数 ≠ 并行度,关键要看 Key 的基数。

3.3 Flink Web Dashboard:实时流的「心电图」

Flink 的 Web Dashboard 和 Spark UI 风格不太一样。它更侧重「实时」和「流式」的监控。如果你做的是实时数仓或流计算,这个工具你必须会用。

3.3.1 SubTask 指标:谁在「偷懒」

打开 Flink Dashboard,进入某个 Job,点击 Task Managers 或 SubTasks 标签页。你会看到每个 SubTask 的:

  • Records Received / Sent:接收和发送的记录数。如果某个 SubTask 接收的记录数远大于其他 SubTask,说明上游数据分发不均匀。
  • Bytes Received / Sent:数据量大小。和 Spark 一样,看最大值和最小值的差距。
  • Duration:处理时间。倾斜的 SubTask 通常处理时间更长。

我习惯把 SubTask 列表按「Bytes Received」排序,一眼就能看出数据分布是否均匀。如果某个 SubTask 接收了 80% 的数据,那不用怀疑——KeyBy 策略出了问题。

3.3.2 Watermark 延迟:倾斜的「间接信号」

Flink 的 Watermark 是衡量事件时间进度的指标。如果某个 SubTask 的 Watermark 明显落后于其他 SubTask,说明这个 SubTask 处理速度慢,数据积压了。

为什么会这样?大概率是因为这个 SubTask 处理的数据量更大,或者遇到了热点 Key。

注意:Watermark 延迟也可能是反压导致的。要区分是「数据倾斜」还是「反压」,可以看 BackPressure 标签页。如果所有 SubTask 都显示高反压,那是资源不足;如果只有个别 SubTask 高反压,那才是数据倾斜。

3.3.3 反压监控:倾斜的「报警器」

Flink 的反压监控非常直观。在 Dashboard 的 BackPressure 标签页,每个 SubTask 会显示一个颜色:

  • 绿色:正常,无反压。
  • 黄色:轻度反压,需要关注。
  • 红色:严重反压,数据已经堵住了。

如果某个 SubTask 长期显示红色,而它的上下游都是绿色,那基本可以断定——这个 SubTask 就是倾斜点。

我的经验:有一次排查 Flink 作业延迟,Dashboard 显示所有 SubTask 都是绿色,但 Watermark 就是不动。后来我点开 Metrics 标签页,发现有个 SubTask 的 numRecordsInPerSecond 是 0——它根本没收到数据!原来是因为 KeyBy 时用了 hash(key) % parallelism,而某个 Key 的 hash 值恰好映射到了一个不存在的 SubTask 上。这种「空转」问题,不看细粒度指标根本发现不了。

3.4 三大工具对比:什么时候用哪个?

场景 首选工具 看什么指标
离线批处理(Spark) Spark UI Stage Duration、Shuffle Read Size、Task 长尾
离线批处理(Hive) Hive Explain Reducer 数、Join 类型、SKEW 标记
实时流处理(Flink) Flink Web Dashboard SubTask 数据量、Watermark 延迟、反压颜色
不确定是哪个引擎 先看日志 WARN/ERROR 日志中的倾斜提示

说白了,工具只是手段。你真正要培养的,是「看到异常指标 → 联想到数据倾斜 → 快速定位热点 Key」的思维链路。这一章讲的是「怎么看」,下一章我会讲「怎么治」——但前提是,你得先学会用这些工具把问题找出来。

本章小结:

  • Spark UI 盯住 Stage 耗时、Task 数据分布、Shuffle Read/Write 三个页面。
  • Hive Explain 重点看 Reducer 数、Join 类型和 SKEW 标记。
  • Flink Dashboard 关注 SubTask 数据量、Watermark 延迟和反压颜色。
  • 诊断是调优的第一步,花 80% 的时间在诊断上,调优才能事半功倍。