Spark 输出文件布局控制
Spark 写出结果的文件布局由三件事决定:partitionBy 决定目录层级,repartition 或 coalesce 决定写出并行度与文件个数,maxRecordsPerFile 限制单个文件的行数。目标是让单个文件落在 128 到 256MB 区间,避免海量 KB 级小文件拖慢后续查询与元数据操作。
基本信息
| 目录层级 | partitionBy |
|---|---|
| 单文件大小 | maxRecordsPerFile(按行数控制) |
| 写出并行度 | repartition / coalesce |
| 目标文件大小 | 128 至 256MB |
| 输出格式 | Parquet / ORC 列式 |
典型使用场景
- 常规落表任务:按 dt 分区写出,先按目标文件大小反推写出并行度
- 数据倾斜:repartition 按分区键重分布,缓解个别任务写出超大文件
- 小结果集:coalesce 收拢到少量文件,避免每个分区产出空文件
- 全量重写:控制并行度与文件数,防止一次任务产生数万个小文件
- 排查小文件:先看写出任务的并行度与分区数,再决定在写入端合并还是只在读取端合并
写出布局
写出布局
spark.conf.set('spark.sql.files.maxRecordsPerFile', 2000000) # 单文件最多约 200 万行
df = spark.table('dws_trade_store_day').where("dt = '2026-10-12'")
df.repartition(32, 'store_id') \ # 32 个写任务,按门店键重分布缓解倾斜
.write.mode('overwrite') \
.partitionBy('dt') \ # 按数据日期分目录
.parquet('/warehouse/dws/trade_store')
# 小结果集改用 coalesce(2) 收拢文件数,避免每分区产出一个空文件并行度控制方式对比
| 方式 | 是否 shuffle | 适用场景 |
|---|---|---|
| repartition(n) | 是,开销较大 | 需要均匀分布文件数 |
| repartition(n, col) | 是 | 按键重分布缓解倾斜 |
| coalesce(n) | 否 | 收拢小结果集的文件数 |
coalesce 不触发 shuffle,但会继承上游分区,上游分布不均时文件大小仍然悬殊;需要均匀分布时要改用 repartition。
用行数控制文件大小只是间接手段,效果取决于单行宽度;先按经验估算单行大小设定参数,跑完一批后看实际落盘大小再回调更靠谱。
写出并行度要跟着数据量走:小数据量用高并行度只会产出大量空文件,大数据量用低并行度则单文件过大、单任务耗时过长。调度脚本里把并行度写成可配置参数,按数据规模滚动调整。
分区写入的数据量跨分区不均匀时,个别分区会产出超大文件或大量小文件;跑完任务后按分区统计文件数与大小分布,比只看总量更能发现问题分区。