为何Pandas用zstd压缩等级10生成的Parquet文件比Spark更小?
Pandas与Spark生成zstd压缩Parquet文件的体积差异原因分析
测试环境与现象
在Ubuntu的ext4原生文件系统环境下,使用Parquet格式并设置zstd压缩等级为10时,Pandas(基于pyarrow引擎)生成的文件体积远小于Apache Spark生成的文件。将Spark生成的Parquet文件通过Pandas加载后重新保存,体积差异显著。
Spark生成代码
df .coalesce(1) .write .option("compression", "zstd") .option("compressionLevel", "10") .mode("overwrite") .parquet(parquetPath)
Pandas重写代码
>>> import pandas as pd >>> df = pd.read_parquet('results/data1.parquet') >>> df.to_parquet('data1.parquet', engine='pyarrow', compression="zstd", compression_level=10, index=False) >>> df = pd.read_parquet('results/data2.parquet') >>> df.to_parquet('data2.parquet', engine='pyarrow', compression="zstd", compression_level=10, index=False)
体积对比统计
| 文件路径 | Apache Spark体积 | Pandas体积 | Pandas/Spark体积比 |
|---|---|---|---|
| results/data1.parquet | 237780532 | 172442433 | 0.72 |
| results/data2.parquet | 62052301 | 41917063 | 0.67 |
软件版本信息
- Apache Spark-4.0.0-preview1
- scala-2.13.14
- Java 21.0.4
- python-3.12.4
- pandas-2.2.3
- pyarrow-19.0.1
补充元数据对比
初始文件列表
pqt$ ls -l -r--r--r-- 1 user user 237780532 May 20 11:55 spark.parquet
元数据查看与重写操作
pqt$ python3 Python 3.12.4 | packaged by Anaconda, Inc. | (main, Jun 18 2024, 15:12:24) [GCC 11.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import pyarrow.parquet as pq >>> import pandas as pd >>> df = pd.read_parquet('spark.parquet') >>> df.to_parquet('pandas.parquet', engine='pyarrow', compression="zstd", compression_level=10, index=False) >>> parquet_file = pq.ParquetFile('spark.parquet') >>> print(parquet_file.metadata) <pyarrow._parquet.FileMetaData object at 0x11e8091de2a0> created_by: parquet-mr version 1.13.1 (build db4183109d5b734ec5930d870cdae161e408ddba) num_columns: 3 num_rows: 20000 num_row_groups: 2 format_version: 1.0 serialized_size: 1001 >>> parquet_file = pq.ParquetFile('pandas.parquet') >>> print(parquet_file.metadata) <pyarrow._parquet.FileMetaData object at 0x11e808d57fb0> created_by: parquet-cpp-arrow version 19.0.1 num_columns: 3 num_rows: 20000 num_row_groups: 1 format_version: 2.6 serialized_size: 1905 >>>
重写后文件列表与体积计算
pqt$ ls -l -rw-rw-r-- 1 user user 172442433 May 20 12:01 pandas.parquet -r--r--r-- 1 user user 237780532 May 20 11:55 spark.parquet pqt$ bc scale = 2 172442433 / 237780532 .72
差异原因分析
- Parquet格式版本与实现库差异
- Spark依赖
parquet-mr 1.13.1生成Parquet 1.0格式,而Pandas基于pyarrow(parquet-cpp-arrow 19.0.1)生成更晚的Parquet 2.6格式。新版本格式在存储布局、元数据编码等方面有优化,能提升压缩效率。
- Spark依赖
- Row Group数量差异
- Spark生成的文件包含2个Row Group,Pandas生成的是1个Row Group。更大的Row Group意味着压缩时可处理的数据块规模更大,zstd这类算法在处理连续大数据块时能找到更多重复模式,进而获得更高压缩比。
- zstd实现细节差异
- Spark的parquet-mr与pyarrow使用的zstd实现版本、参数调优逻辑可能存在差异,即使压缩等级同为10,实际压缩效果也会不同。
- 列存储编码策略差异
- 作为列存格式,不同Parquet实现库在列数据编码方式、字典编码的使用策略上有区别。pyarrow可能采用了更高效的列编码方式,配合zstd压缩进一步降低文件体积。
内容的提问来源于stack exchange,提问作者Quiescent
相关产品推荐
相关产品推荐

