读取和写入 Apache ORC 格式#

Apache ORC 项目提供了一种标准化的开源列式存储格式,用于数据分析系统。它最初是为 Apache Hadoop 创建的,随后 Apache DrillApache HiveApache ImpalaApache Spark 等系统将其采用为高性能数据 IO 的共享标准。

Apache Arrow 是处理 ORC 文件读写时理想的内存中表示层。

获取支持 ORC 的 pyarrow#

如果您通过 pip 或 conda 安装了 pyarrow,它通常会默认捆绑 ORC 支持。

>>> from pyarrow import orc

如果您是从源码构建 pyarrow,则必须在编译 C++ 库时使用 -DARROW_ORC=ON,并在构建 pyarrow 时启用 ORC 扩展。更多详细信息请参阅 Python 开发 页面。

读取和写入单个文件#

read_table()write_table() 函数分别用于读取和写入 pyarrow.Table 对象。

让我们看一个简单的表

>>> import numpy as np
>>> import pyarrow as pa

>>> table = pa.table(
...     {
...         'one': [-1, np.nan, 2.5],
...         'two': ['foo', 'bar', 'baz'],
...         'three': [True, False, True]
...     }
... )

我们使用 write_table 将其写入 ORC 格式

>>> from pyarrow import orc
>>> orc.write_table(table, 'example.orc')

这将创建一个单个 ORC 文件。在实践中,ORC 数据集可能由多个目录中的许多文件组成。我们可以使用 read_table 读取单个文件

>>> table2 = orc.read_table('example.orc')

您可以传入要读取的列子集,这比读取整个文件要快得多(得益于其列式布局)

>>> orc.read_table('example.orc', columns=['one', 'three'])
pyarrow.Table
one: double
three: bool
----
one: [[-1,nan,2.5]]
three: [[true,false,true]]

我们不必使用字符串来指定文件的来源。它可以是以下任何一种:

  • 作为字符串的文件路径

  • Python 文件对象

  • pathlib.Path 对象

  • PyArrow 中的 NativeFile

通常情况下,Python 文件对象的读取性能最差,而文件路径字符串或 NativeFile 实例(尤其是内存映射)的性能表现最佳。

我们还可以通过 pyarrow.dataset 接口读取包含多个 ORC 文件的分区数据集。

另请参阅

数据集相关文档.

ORC 文件写入选项#

write_table() 提供了多种选项来控制写入 ORC 文件时的各项设置。

  • file_version:要使用的 ORC 格式版本。'0.11' 可确保与旧版本读取器兼容,而 '0.12' 是较新的版本。

  • stripe_size:控制列条带(stripe)内数据的大致大小。默认值为 64MB。

更多详细信息请参阅 write_table() 的文档字符串。

更细粒度的读写#

read_table 使用 ORCFile 类,该类还具有其他功能

>>> orc_file = orc.ORCFile('example.orc')
>>> orc_file.metadata

-- metadata --
>>> orc_file.schema
one: double
two: string
three: bool
>>> orc_file.nrows
3

更多详细信息请参阅 ORCFile 的文档字符串。

正如您可以在 Apache ORC 格式 中了解到的,ORC 文件由多个条带(stripes)组成。read_table 会读取所有条带并将它们合并成一个单独的表。您可以使用 read_stripe 读取单个条带

>>> orc_file.nstripes
1
>>> orc_file.read_stripe(0)
pyarrow.RecordBatch
one: double
two: string
three: bool
----
one: [-1,nan,2.5]
two: ["foo","bar","baz"]
three: [true,false,true]

我们可以使用 ORCWriter 写入 ORC 文件

>>> with orc.ORCWriter('example2.orc') as writer:
...     writer.write(table)

压缩#

行组中列内的数据页可以在编码过程(字典编码、RLE 编码)后进行压缩。在 PyArrow 中,默认不使用压缩,但同时也支持 Snappy、ZSTD、Zlib 和 LZ4

>>> orc.write_table(table, 'example.orc', compression='uncompressed')
>>> orc.write_table(table, 'example.orc', compression='zlib')
>>> orc.write_table(table, 'example.orc', compression='zstd')
>>> orc.write_table(table, 'example.orc', compression='snappy')

Snappy 通常能带来更好的性能,而 Zlib 则可能产生更小的文件。

从云存储读取#

除了本地文件外,pyarrow 还通过 filesystem 关键字支持其他文件系统,例如云存储文件系统

>>> from pyarrow import fs

>>> s3  = fs.S3FileSystem(region="us-east-2")
>>> table = orc.read_table("bucket/object/key/prefix", filesystem=s3)

另请参阅

文件系统相关文档.