Parquet:面向大数据分析的列式存储格式

type
Post
status
Published
date
slug
summary
tags
category
Python知识与技巧
icon
password
网址
作者
标签
文章链接
发布时间
来源
在大数据分析与数据工程场景里,CSV/JSON 往往好用,但不够快、不够省空间,还不利于只读取部分字段。Parquet开源的列式存储文件格式,专为分析型负载(OLAP)设计,擅长在“存得更小、读得更快”的同时兼顾跨平台兼容性与生态工具链。Python 作为一种功能强大且灵活的编程语言,提供了多种库来读写 Parquet 文件,如 pandas 和 pyarrow

1. Parquet 是什么?为什么它适合分析型场景

1.1 列式存储:只读需要的列

Parquet 的核心是按列存储:同一列的数据连续存放在一起。这样当你只需要读少数几个字段(比如 columns = [user_id, timestamp])时,可以只读取相关列,避免把整行所有列都扫一遍,从而显著减少 I/O 与内存开销。[1]
💡
  • 行式存储:数据按行存储,每一行的数据连续存储在一起。适用于关系型数据库,因为它可以快速读取整行数据。
  • 列式存储:数据按列存储,同一列的数据连续存储在一起。适用于数据分析系统,因为它可以只读取需要的列,减少 I/O 开销。

1.2 高压缩率:同列同类型带来的“可压缩性”

Parquet 往往能比 CSV/JSON 获得更高压缩率。原因在于同一列通常类型一致、分布更集中、重复值更多,更利于编码与压缩。

1.3 高效查询:元数据与谓词下推(Predicate Pushdown)

Parquet 文件通常包含元数据(例如列统计信息如 min/max 等)。结合列式结构,很多查询引擎可以做谓词下推:在真正读取数据块之前就过滤掉不可能命中的部分,从而进一步加速分析查询。[1]

1.4 生态与兼容性:跨平台通用

Parquet 最初在 Hadoop 生态中发展,如今被 Spark、Hive、Impala 等广泛采用,也是云数据湖/数仓常见的底层文件格式之一。[2][1]

2. Python 读写 Parquet:pandas 与 PyArrow 的两条主线

在 Python 世界里,最常见的组合是:
  • pandas:面向数据分析用户的高层接口(to_parquet / read_parquet
  • PyArrow:提供 Arrow 内存表(pyarrow.Table)与 Parquet 的底层读写能力(pyarrow.parquet
其中 pandas 的 DataFrame.to_parquet() 提供了非常实用的一站式能力:指定引擎、压缩、是否写入索引、分区写出、远程存储参数等。[3]

3. 用 pandas 写 Parquet:to_parquet

3.1 最简单的保存与读取

to_parquet 会把 DataFrame 写成 Parquet 文件;read_parquet 再读回来。[3]

3.2 引擎(engine):pyarrow vs fastparquet

pandas 支持多个 Parquet 引擎:
  • engine="auto":自动选择(优先 pyarrow,否则 fastparquet
  • engine="pyarrow":更常见的选择
  • engine="fastparquet":在某些旧系统/环境中也常用[3]

3.3 压缩(compression):速度与体积的权衡

常见压缩选项包括 snappy(默认,速度与压缩率平衡)、gzip(压缩率高但慢)、zstd(综合表现优秀)等。[3]

3.4 是否写入索引(index)

索引写入会带来额外存储开销;如果索引不重要,建议关闭:
pandas 文档/示例也展示了 index=False 的常见用法。[3]

3.5 分区写出(partition_cols):更适合数据湖目录组织

当数据量大、查询常按某些维度过滤(例如日期、地区、业务线),可以分区写出:
这会输出为目录结构(而不是单一文件),方便后续按分区裁剪读取。[3]

3.6 只读取部分列

在读取 Parquet 文件时,有时只需要读取部分列,以减少内存使用。可以使用 columns  参数指定需要读取的列。

4. 用 PyArrow 读写 Parquet:更底层、更可控

PyArrow 的 Parquet 文档给出了非常系统的操作范式:将 pandas DataFrame 转为 pyarrow.Table,再用 pyarrow.parquetwrite_table / read_table 完成读写。[2]

4.1 写入单个 Parquet 文件:write_table

这与官方示例一致:pa.Table.from_pandas + pq.write_table[2]

4.2 只读取部分列:read_table(columns=...)

由于 Parquet 的列式布局,这种“列裁剪”在读取时通常能显著节省时间与内存。[2]

4.3 索引是否保留:preserve_index=False

pa.Table.from_pandas 默认会保存 pandas 的 index(通过额外列记录)。如果索引不重要,可以:
然后读回 pandas 时索引会变成默认 RangeIndex。[2]

4.4 检查元数据:ParquetFile / read_metadata

当你需要调试文件结构、行组(row group)、编码/压缩等信息时:
这对于分析性能(例如行组大小、列统计信息是否存在)很有帮助。[2]

4.5 多文件数据集与分区:write_to_dataset

当数据量大到需要“目录 + 多文件”方式组织时,PyArrow 也支持直接写分区数据集:
并可读取整个目录作为数据集。[2]

4.6 过滤数据

在读取 Parquet 文件时,可以使用 filters参数过滤数据。

5. 实战建议:如何选择参数与工作流

  1. 选择合适的库
      • pandas:适用于处理小规模数据,代码简洁,易于使用。
      • pyarrow:适用于处理大规模数据,性能更高,支持更多的高级功能,如过滤数据。
  1. 压缩算法怎么选
      • snappy:默认推荐,综合速度好(写入/读取都快)[3]
      • gzip:更小但更慢(更适合冷存储或网络传输敏感场景)[3]
      • zstd:很多情况下是更好的平衡选择(兼顾速度与压缩率)[3]
  1. 索引是否写入
      • 分析任务里,索引常常只是临时产物;如果不需要,建议 index=False(pandas)或 preserve_index=False(PyArrow)。[3][2]
  1. 数据湖/离线数仓:分区优先
    1. 如果你经常按日期、地区、业务线过滤,分区目录结构能减少扫描范围:pandas 的 partition_cols 或 PyArrow 的 write_to_dataset(partition_cols=...) 都是常见方案。[3][2]

参考文献

  1. pandas DataFrame.to_parquet() 保存为 parquet 文件(参数与示例)
  1. 南瓜慢说知识库:Parquet 文件(概念、优势、压缩原理、应用场景与 Python 示例)
  1. Apache Arrow 文档:Reading and Writing the Apache Parquet Format(PyArrow 读写、列裁剪、元数据、数据集分区等)
 
上一篇
弱知产保护与跨国公司的技术探索
下一篇
政府资本进入,是否一定会推动企业绿色创新?
Loading...
文章列表
Practice makes perfect
文献集锦
如何理论创新?
管理学理论集锦
Python实际应用
聚类标准误与固定效应
巫师3:狂猎
Stata应用技巧
Python知识与技巧
回归系数的经济意义
双重差分法(DID)
创新文献阅读与摘要
计量经济学
Python绘图相关
遗漏变量偏误检验