Spark Repartition 和 Coalesce 有什么区别?
面试怎么回答
repartition 会通过 Shuffle 重新分布数据,可增加或减少分区,分布通常更均匀;coalesce 默认尽量合并现有分区,主要用于减少分区,成本较低但可能不均衡。我会根据调整方向、当前倾斜程度和后续计算量选择:过滤后写文件可优先 coalesce,增加并行度或需要重新均衡则用 repartition,同时避免无脑 coalesce(1)。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
很多人只会回答:
“repartition 有 Shuffle,coalesce 没有 Shuffle。”
方向没错,但生产里更重要的是:为什么要改分区、是增加还是减少,以及愿不愿意用一次 Shuffle 换取更均匀的数据分布。
分区调整不是改一个数字,而是在并行度、数据均衡和 Shuffle 成本之间做选择。
先说核心区别
Repartition:重新洗牌并均匀分配
repartition(n) 会触发 Shuffle,可以增加或减少分区。
它适合:
- 上游分区明显倾斜,需要重新均衡
- 进入重计算前需要提高并行度
- 按某个字段重新组织分区
- 输出分区数与上游完全不同
代价是网络传输、序列化和磁盘读写。
Coalesce:尽量合并现有分区
coalesce(n) 默认不触发 Shuffle,通常用于减少分区。它把多个旧分区合并到较少的新分区,成本低,但不保证数据均匀。
它适合过滤后数据量大幅下降、只想减少空分区或小文件的场景。

怎么选择?看三个问题
第一问:要增加还是减少分区?
增加分区通常选择 repartition。减少分区时,两者都能做到,但是否需要均衡决定最终选择。
第二问:当前数据是否倾斜?
如果旧分区大小差异很大,直接 coalesce 可能把多个大分区继续堆到同一个新分区,导致下游少数 Task 很慢。
这时用 repartition 多付一次 Shuffle,换取更均匀的任务负载,可能反而让总耗时更短。
第三问:后面还有没有重计算?
如果只是过滤后写文件,coalesce 往往足够。如果后面还有 Join、聚合或复杂计算,分区不均的代价会被持续放大,更应该评估 repartition。
一个典型反例
比如一份数据从 200 个分区过滤到只剩原来的很小一部分。为了只输出一个文件,直接 coalesce(1)。
结果所有数据都由一个 Task 写出,整体速度受单个 Executor、单线程和单磁盘吞吐限制,文件稍大就会拖慢任务甚至出现内存压力。
更合理的做法是根据目标文件大小和下游读取方式保留多个输出分区,而不是把“文件少”简单理解成“只能有一个文件”。
减少小文件,不等于把全部数据塞进一个分区。