使用Pandas/PyArrow重写Parquet文件后体积变大,求配置方案
Parquet读写后文件体积增大的问题
问题背景
我需要将Parquet文件读入内存,选取部分数据上传至AWS S3 Bucket,原本计划通过文件大小或MD5哈希校验上传是否正确,但发现不管是以字节流、pd.DataFrame还是PyArrow Table形式读入后重写,文件体积都会增大。
复现代码
Pandas读写方式
import pandas as pd from io import ByteIO # 读取原文件 df = pd.read_parquet("data/example.parquet") # 重写文件 buffer = ByteIO() df.to_parquet(buffer) with open('copy.parquet', 'wb') as f: f.write(buffer.getvalue())
PyArrow读写方式
import pyarrow as pa import pyarrow.parquet as pq # 读取原文件 with open('data/example.parquet', 'rb') as f: buffer = pa.BufferReader(f.read()) table = pq.read_table(buffer) # 重写文件 pq.write_table(table, 'copy.parquet')
现象
- 文件大小对比(
ls -l输出):
37089 Oct 28 16:57 data/example.parquet 37108 Dec 7 14:17 copy.parquet
- 用
xxd+diff对比,二进制差异遍布整个文件,并非仅元数据不同 - 重新读取两个文件得到的DataFrame内容完全一致
- 文件包含NaN和NaT值
- 开启
compression='snappy'后情况依旧
提问
请问我在写入时是否遗漏了某些配置?
可能的原因及解决方法
1. 对齐原文件的写入参数
原文件的写入可能使用了特定的压缩、编码或页大小参数,默认重写参数与之不符导致体积变化。先读取原文件的元信息获取配置:
import pyarrow.parquet as pq parquet_file = pq.ParquetFile("data/example.parquet") # 查看各列的压缩方式 for col in parquet_file.metadata.row_groups[0].columns: print(f"列 {col.path_in_schema} 压缩方式: {col.compression}") # 估算页大小 sample_col = parquet_file.metadata.row_groups[0].columns[0] page_size = sample_col.total_byte_size / sample_col.num_pages print(f"估算页大小: {int(page_size)}")
写入时指定相同参数,例如:
pq.write_table( table, 'copy.parquet', compression='snappy', # 匹配原文件压缩方式 data_page_size=int(page_size), # 匹配原文件页大小 use_dictionary=True # 若原文件启用字典编码则开启 )
2. 指定缺失值编码方式
Parquet对NaN/NaT的存储编码可能存在差异,尝试指定更紧凑的编码:
from pyarrow.parquet import ParquetWriter writer = ParquetWriter( 'copy.parquet', table.schema, compression='snappy', encoding='BIT_PACKED', # 针对缺失值更紧凑的编码 write_statistics=False # 关闭统计信息减少额外数据 ) writer.write_table(table) writer.close()
3. 匹配原文件的行组大小
行组大小会影响压缩效率,指定与原文件一致的行组大小:
row_group_size = parquet_file.metadata.row_groups[0].num_rows pq.write_table(table, 'copy.parquet', row_group_size=row_group_size)
4. 关闭冗余元数据生成
部分元数据(如统计信息、额外schema信息)可能增加文件体积,尝试关闭:
pq.write_table( table, 'copy.parquet', write_statistics=False, store_schema=False )
内容的提问来源于stack exchange,提问作者Amirrad
相关产品推荐
相关产品推荐

