You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

spark.sql.files.maxPartitionBytes无法正确限制分区大小的原因探究

回答

核心逻辑:Spark 读取Parquet的分区规则

Spark 处理Parquet文件时,有两个关键限制和逻辑:

  1. 不可拆分Row Group:Parquet的Row Group(行组)是存储的最小不可拆分单元,Spark无法将单个Row Group拆分成多个分区,无论maxPartitionBytes设得多小。
  2. maxPartitionBytes是建议值:该参数只是Spark分区规划的目标参考,最终分区大小还会结合spark.sql.files.openCostInBytes(默认4MB,衡量打开文件的开销)权衡——Spark不会为了严格贴合目标值,过度增加文件打开次数。

实验1疑问解答

1. 分区大小为何超过90MB?

你的每个155MB左右的Parquet文件,内部包含两个Row Group:一个约127MB(接近Parquet默认的128MB Row Group大小),一个约29MB。由于Spark不能拆分Row Group,那个127MB的Row Group只能完整作为一个分区,自然超过了90MB的设定值。

2. 为何不合并29MB的小分区?

Spark合并小分区的前提是:合并后的总大小接近maxPartitionBytes,且不会带来过高的文件打开开销。90MB的目标下,至少需要3个29MB的小分区才能凑到接近目标的大小,但这些小分区来自不同的Parquet文件,合并它们需要打开多个文件,openCostInBytes的存在让Spark认为这种合并的开销大于收益,因此不会主动合并。


实验2疑问解答

1. 分区数量为何变为22?

原始的16个Parquet文件共包含32个Row Group(16个~127MB大Row Group + 16个~29MB小Row Group):

  • 所有~127MB的大Row Group因超过120MB,只能单独成为分区(共16个);
  • 小Row Group会被尝试合并:4个29MB的总和是116MB,接近120MB的目标,因此部分小Row Group被合并成单个分区。16个小Row Group按4个一组合并,可得到4个分区,但实际因Row Group大小略有差异,最终合并出6个小分区,加上16个大分区,总数量为22个。

2. 分区大小为何仍有偏差?

分区只能基于已有的Row Group组合:

  • 大Row Group本身就超过120MB,无法拆分只能保留;
  • 小Row Group合并时,只能按整数个组合,无法精确凑到120MB(比如3个29MB是87MB,4个是116MB),因此分区大小必然存在偏差。

优化建议

如果想要更精准的分区控制,建议在写入Parquet文件时,通过parquet.block.size参数(单位字节)调整Row Group大小,让其接近你期望的maxPartitionBytes值。这样读取时,Spark就能直接基于匹配的Row Group创建符合预期的分区。

内容的提问来源于stack exchange,提问作者Nikolaos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:24:54