Spark中repartition与coalesce在S3读写场景下的性能差异疑问
Spark中repartition与coalesce在S3读写场景下的性能差异疑问
这问题确实有点反直觉,我来帮你拆解下背后的原因,结合你的场景一步步分析:
先明确两个算子的核心差异
首先得搞清楚repartition和coalesce在减少分区时的本质区别:
repartition(N):不管是增加还是减少分区,都会触发全量shuffle。它会先对所有数据做重新分配,确保每个新分区的数据量尽量均匀,这个过程会经历「map阶段并行处理所有上游分区 → shuffle传输数据到对应节点 → reduce阶段生成N个新分区」。coalesce(N):默认情况下是无shuffle的分区合并,它只是把上游的多个小分区直接“打包”成N个大分区,不会重新分配数据的位置——也就是说,合并的分区必须是物理上相邻的(或者说属于同一个节点的),不会跨节点移动数据来平衡分区大小。
结合你的场景分析为什么coalesce更慢
你的场景是:处理5TB输入后得到5GB结果,用相同集群(5 worker × 16核)测试三种写入方式,结果coalesce(11)远慢于另外两种,核心原因有两个:
1. 并行度被严重浪费
你的集群总共有80个可用vCPU(5 worker × 16核),但coalesce(11)会直接把写入阶段的任务数降到11——这意味着大部分CPU核心都在闲置!
- 「默认多文件」和
repartition(11):前者的任务数等于处理后DataFrame的分区数(假设是几十甚至上百个),后者在shuffle的map阶段也会用上所有上游分区的任务数,充分利用集群的多核并行能力,所以整体能在6小时完成。 - 而
coalesce(11)只有11个任务在处理所有5GB结果的读取和写入,相当于用11个核心扛下了原本80个核心的工作量,速度自然慢很多。
2. S3的读写特性放大了coalesce的劣势
S3作为对象存储,对连续大文件的读写性能远好于分散小文件的随机读写:
repartition(11)经过shuffle后,每个最终的分区数据是均匀且连续的,写入S3时是一次性写入大文件,能充分利用S3的带宽。coalesce(11)是直接合并上游的小分区(这些小分区可能分散在S3的不同路径、甚至集群的不同节点上),每个coalesce任务需要从多个分散的位置读取小文件,再合并成大文件写入——这种随机IO+跨节点数据拉取的组合,会大幅增加读写的延迟,进一步拖慢整体速度。
额外补充:什么时候coalesce才会更快?
coalesce的无shuffle优势只有在上游分区已经集中在少数节点,且分区数不多的场景下才会体现。比如:你已经通过shuffle把数据聚集到了20个分区,这时候用coalesce(11)合并,因为不需要再shuffle,速度会比repartition(11)快。但你的场景中,上游处理后的分区显然是分散且数量较多的,这时候coalesce的劣势就完全暴露了。
备注:内容来源于stack exchange,提问作者Matthew
相关产品推荐
相关产品推荐

