应使用 pyarrow.dataset() + to_table(columns=...) 组合实现真正的列裁剪,避免 pandas.read_parquet() 的伪列筛选;配合 filter 参数跳过不匹配分区,设置 batch_size 和 use_threads 优化内存与性能,并注意字典编码和类型不一致问题。

用 pyarrow.dataset 按需读取列,避免全量加载
Parquet 文件本身支持列式存储和元数据跳过,但直接用 pandas.read_parquet() 读大文件时,默认会解压并加载所有列到内存——哪怕你只想要其中一两列。真正高效的做法是绕过 pandas 的封装,用 pyarrow.dataset 构建懒加载的数据集,再通过 to_table() 显式指定 columns 参数。
常见错误是写成 pandas.read_parquet("big.pq", columns=["col_a", "col_b"]):这个参数在某些 PyArrow 版本下看似生效,实则底层仍可能扫描全部列的页首元数据,尤其当文件分块多、schema 复杂时,I/O 和内存开销远超预期。
- 优先用
pyarrow.dataset()+to_table(columns=...)组合,它能真正跳过未请求列的页数据读取 - 确保 Parquet 文件是按列独立压缩(默认行为),且没有嵌套 schema 中的冗余字段干扰列裁剪
- 如果文件由 Spark 或 DuckDB 写出,检查是否启用了
dictionary_enabled=False或use_dictionary=False—— 字典编码可能让列裁剪失效
处理分区目录结构时,filter 要配合 columns 一起用
真实场景中,超大 Parquet 往往按日期/类别分区,比如 data/year=2023/month=04/day=15/。这时光指定列还不够,必须叠加过滤条件,否则 dataset 会遍历所有子目录。
错误做法是先 to_table() 再用 pandas .query() 过滤:这等于把所有分区数据都拉进内存再筛,完全失去列存优势。
- 用
ds.field("year") == 2023这类表达式传给to_table(filter=...),PyArrow 会自动跳过不匹配的分区目录 -
filter和columns可同时生效,顺序无关,但必须都在to_table()调用里声明 - 避免在 filter 中使用自定义函数或 pandas 表达式,PyArrow 只认
pyarrow.compute支持的谓词
内存峰值仍高?检查 use_threads 和 batch_size
即使只读几列,如果单个 RowGroup 过大(比如 >500MB),PyArrow 默认会一次性解压整个 RowGroup,导致瞬时内存飙升。这不是 bug,而是列存格式的固有特性:同一行的不同列值分散在不同页中,但 RowGroup 是最小的可跳过单位。
- 设置
batch_size=10000(或更小)让to_table()分批读取,缓解内存压力 -
use_threads=True(默认)能加速解压,但会增加线程开销;对 SSD 环境通常有益,对 HDD 可能反而拖慢 - 若文件由
fastparquet写出,确认其write_index=False,否则索引列会被隐式读入
遇到 ArrowInvalid: Unable to cast array 类型冲突怎么办
当你只读部分列,而这些列在不同 RowGroup 中有不一致的物理类型(例如某列在前 10 个 RowGroup 是 int32,后 10 个是 int64),PyArrow 在拼接 Table 时可能报 ArrowInvalid。这不是数据损坏,而是 Parquet writer 允许 per-RowGroup 类型优化的结果。
- 加
schema=pa.schema([("col_a", pa.int64())])强制统一类型,让 PyArrow 自动做 cast - 或改用
scanner()+to_reader()流式处理,每批单独 cast,避免一次性合并 - 长期方案:重写 Parquet 时加
coerce_int96_timestamp_unit="us"和data_page_size=1024*1024,减少类型漂移
最易被忽略的是:列裁剪效果高度依赖 Parquet 文件的写入方式。用 Spark 写时加 .option("parquet.enable.dictionary", "false"),用 PyArrow 写时设 use_dictionary=False,才能确保列裁剪不被字典页干扰。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











