不应使用 fastparquet 写 Parquet 文件,因其纯 Python 实现缺乏零拷贝和并行压缩,性能比 PyArrow 慢 2–4 倍且不支持关键压缩参数;生产环境应选用 PyArrow 并调优 compression、row_group_size、use_dictionary 和 data_page_size 四个参数,配合分区写入与结构验证以保障效率。

Fastparquet 本身不擅长优化写入效率,它更适合读取场景下的精细控制;真正提升存储效率的关键在 PyArrow 的参数调优和文件组织方式。
为什么不要用 fastparquet 写 Parquet 文件
fastparquet 的写入路径是纯 Python 实现,缺乏底层零拷贝和并行压缩能力。实测中,同样 5GB 的宽表数据,pd.to_parquet(engine="fastparquet") 比 pd.to_parquet(engine="pyarrow") 慢 2–4 倍,且不支持 use_dictionary 写入、data_page_size 控制等关键压缩参数。
如果你看到文档里提到 “fastparquet 支持写入”,那是指基础功能可用,不是性能推荐项。生产环境写 Parquet,请直接切到 pyarrow 引擎。
PyArrow 写入时必须调整的 4 个参数
默认 to_parquet() 虽能跑通,但生成的文件往往 IO 效率低、压缩率差、查询慢。以下参数组合能显著改善:
立即学习“Python免费学习笔记(深入)”;
-
compression="snappy":比默认"lz4"更通用,解压速度与压缩率平衡较好;"zstd"在高压缩需求下更优(需 pyarrow ≥ 10.0) -
row_group_size=1_000_000:控制每个 row group 行数。太小(如 10k)会导致元数据膨胀、谓词下推失效;太大(如 10M)会让过滤时跳过成本变高 -
use_dictionary=True(对 string / category 列):启用字典编码,大幅减少重复字符串的存储体积;若列基数极高(如 UUID),可设为False -
data_page_size=65536(即 64KB):影响页内压缩粒度和内存缓存效率,64KB 是多数 SSD 随机读的友好边界
示例:
df.to_parquet(
"output.parquet",
engine="pyarrow",
compression="snappy",
row_group_size=1_000_000,
use_dictionary=True,
data_page_size=65536
)
分区写入比单文件更关键
Parquet 的性能优势在“分区”结构上才能真正释放。比如爬虫数据按 date 和 source 分区:
- 避免把所有数据塞进一个
.parquet文件 —— 这会丧失谓词下推能力 - 用
partition_cols=["date", "source"]参数让to_parquet()自动生成目录结构:date=2026-06-20/source=xxx.com/... - 后续读取时,
filters=[("date", ">=", "2026-06-20")]可直接跳过无关目录,IO 减少 90%+
注意:partition_cols 只在 pyarrow 引擎下稳定支持;fastparquet 对多级分区支持弱,且不保证统计信息写入完整。
写入后务必验证文件结构
写完别急着读,先检查是否真生效:
- 用
pyarrow.parquet.read_metadata("output.parquet")看num_row_groups和各 row group 的num_rows是否符合预期 - 用
pyarrow.parquet.read_schema("output.parquet")确认 string 列是否用了dictionary编码(type 为dictionary<values: string, indices: int32>) - 用
ls -lh对比文件大小 —— 同样数据,开启use_dictionary+snappy通常比默认设置小 30–50%
最容易被忽略的是:分区目录下没有 _metadata 文件,或 row group 统计信息为空 —— 这意味着后续 filters 会退化为全量扫描,所有优化都白做。


















