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

从Parquet文件加载到Arrow表时的数据内存占用预估问题

问题解答

一、Parquet元数据参数含义澄清

你确实误解了这两个参数的统计范围,它们本身是可靠的,只是和你预期的统计对象不一致:

  • total_compressed_size:不是Parquet文件的总存储大小,它仅统计文件中列数据页的压缩后字节数,不包含Schema、行组索引、文件级元数据等额外部分,所以会比实际文件的4MB小。
  • total_uncompressed_size:不是数据在内存中的实际占用大小,它只计算列数据页解压后的原始字节数(仅指页内的纯数据,不考虑PyArrow在内存中存储时的对象头、类型描述、内存对齐等额外开销),因此远小于你看到的20MB内存占用。

你的场景里,大量列是全行相同值,Parquet会自动用字典编码+压缩处理,数据页本身极小,所以这两个参数都只有2MB左右,和实际文件、内存占用的差异完全是统计范围不同导致的。

二、加载前预估Parquet内存占用的可靠方法

1. 基于Parquet元数据计算近似值

通过读取文件元数据,结合数据类型和统计信息估算:

  • 先获取每列的数据类型(比如int32占4字节/行,float64占8字节/行),乘以总行数得到基础字节数
  • 对于字符串等可变长度类型,利用元数据中存储的total_byte_size统计值累加
  • 最后加上PyArrow内存存储的额外开销(一般按10%-20%估算,对应内存中数据结构的额外占用)

示例代码(PyArrow):

import pyarrow.parquet as pq

# 读取Parquet文件元数据
pq_file = pq.ParquetFile("target_file.parquet")
schema = pq_file.schema
total_rows = pq_file.metadata.num_rows

estimated_mem = 0
for field in schema:
    # 处理固定长度类型
    if hasattr(field.type, 'bit_width'):
        byte_per_row = field.type.bit_width // 8
        estimated_mem += byte_per_row * total_rows
    # 处理可变长度类型(如string)
    else:
        for row_group in pq_file.metadata.row_groups:
            col_stat = row_group.column(field.name).statistics
            if col_stat and hasattr(col_stat, 'total_byte_size'):
                estimated_mem += col_stat.total_byte_size

# 加上PyArrow内存额外开销,按15%估算
estimated_mem *= 1.15
print(f"预估内存占用: {estimated_mem / (1024*1024):.2f} MB")

2. 采样加载推算

如果元数据统计信息不全,可以加载小比例的行数据,按比例推算整体内存:

# 加载第一个行组作为样本
sample_table = pq.read_table("target_file.parquet", row_groups=[0])
sample_mem = sample_table.nbytes
# 按样本行数和总行数的比例估算
total_estimated = sample_mem * (total_rows / len(sample_table))
print(f"预估内存占用: {total_estimated / (1024*1024):.2f} MB")

3. 利用完整统计信息汇总

如果写入Parquet时开启了统计信息(默认开启),可以直接汇总每列的total_byte_size,再加上PyArrow的额外开销,这是最接近实际内存占用的估算方式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:12:34