使用Pandas过滤Parquet文件后体积增大的原因排查
Pandas过滤Parquet后文件变大的原因及解决方法
这种过滤后数据量减少但Parquet文件反而变大的情况,核心是原文件的存储优化策略在写入新文件时没有被继承,具体原因如下:
压缩参数不匹配:原Parquet文件可能采用了高压缩比的算法(如GZIP、ZSTD),而
df.to_parquet()默认使用Snappy(压缩速度快但压缩比中等)。如果原文件用了GZIP这类压缩率更高的算法,即使过滤后数据量减少,用默认参数写入的新文件体积也可能超过原文件。另外,部分原文件可能设置了精细的压缩级别,而默认写入未配置对应参数。行组(Row Group)优化丢失:Parquet作为列存储格式,原文件的行组大小通常经过优化(推荐128MB-256MB),这种大尺寸行组能提升压缩效率并减少元数据开销。但过滤后写入新文件时,默认会生成较小的行组(甚至单条数据一个行组),小行组不仅压缩效果差,还会导致元数据体积大幅增加,最终整体文件变大。
字典编码未启用或失效:原文件可能对重复值多的低基数列(如ID、类别列)启用了字典编码,这种编码能大幅压缩这类列的存储体积。但过滤后写入时如果未显式开启字典编码,或者过滤后列的基数变化导致字典编码效果下降,会直接让列的存储体积膨胀。
读写引擎不一致:读取和写入Parquet时若使用不同引擎(如读用PyArrow、写用Fastparquet,反之亦然),两个引擎的默认存储优化参数(压缩方式、行组大小、编码策略等)存在差异,也会导致文件体积出现反常变化。
对应解决办法
- 匹配原文件压缩参数:先确认原文件的压缩方式,写入时指定相同的算法和级别,示例:
filtered_df.to_parquet('path/to/save/filtered.parquet', compression='gzip', compression_level=9) - 控制行组大小:写入时设置合适的行组尺寸,以PyArrow引擎为例:
filtered_df.to_parquet('path/to/save/filtered.parquet', engine='pyarrow', row_group_size=1000000) - 启用字典编码:对低基数列显式开启字典编码,示例:
import pandas as pd import pyarrow as pa import pyarrow.parquet as pq table = pa.Table.from_pandas(filtered_df) # 为指定列设置字典编码 modified_schema = table.schema target_cols = ['id', 'category'] # 替换为你的低基数列 for col in target_cols: field = modified_schema.field(col) modified_schema = modified_schema.set(col, field.with_metadata({'ARROW:encoding': 'DICTIONARY'})) pq.write_table(table, 'path/to/save/filtered.parquet', schema=modified_schema, compression='snappy') - 统一读写引擎:读取和写入使用同一引擎,避免参数差异,示例:
df = pd.read_parquet('path/to/file.parquet', engine='pyarrow') filtered_df.to_parquet('path/to/save/filtered.parquet', engine='pyarrow')
内容的提问来源于stack exchange,提问作者basigow
相关产品推荐
相关产品推荐

