我可以通过索引访问 Parquet 文件而不将整个文件读入内存吗?

Posted

技术标签:

【中文标题】我可以通过索引访问 Parquet 文件而不将整个文件读入内存吗?【英文标题】:Can I access a Parquet file via index without reading the entire file into memory? 【发布时间】:2021-05-18 21:00:28 【问题描述】:

我刚刚读到 HDF5 允许您在不将整个文件读入内存的情况下访问数据。

在没有 Java(非 pyspark 解决方案)的 Parquet 文件中是否可以进行这种搜索行为?由于强大的 dtype 支持,我正在使用 Parquet。

import h5py

f = h5py.File('my_file.hdf5', 'w')
dset = f.create_dataset('coords', data=my_ndarray)
f.close()

f = h5py.File('my_file.hdf5', 'r')
dset = f['coords']
my_array = dset[-2:]

https://arrow.apache.org/docs/python/parquet.html#inspecting-the-parquet-file-metadata

我在这里看到 Parquet 元数据有 num_row_groups: 1 (or more)。但我不确定这如何帮助我获取行 [23、42、117、99293184]。

【问题讨论】:

当然,您可以将元数据写入 parquet 文件,并使用该元数据“索引”包含您想要的数据的特定行组。 我有点不确定你在追求什么。您是在询问 Parquet 是否支持随机访问?例如,您没有使用 HDF5 并且想要类似的功能? 或者你是在问HDF5的随机访问是否足以支持parquet的部分读取模型?例如,您将 parquet 文件存储在 HDF5 存储中。 @Pace 是的,我想从 parquet 中获取行列表 【参考方案1】:

Parquet 允许某些形式的部分/随机访问。但是,它是有限的。每个 parquet 文件由一个或多个行组组成,每个 parquet 文件由一个或多个列组成。您可以检索所需的行组和列的任意组合。

只有一种方法可以将列存储在 parquet 文件中。但是,如何将行分配到行组取决于文件的创建者。创建者可以将每一行放在自己的行组中(尽管这样做效率太低),或者他们可以选择为整个文件使用一个行组(这很常见)。

这意味着进行部分读取的能力将取决于文件的创建方式。如果您正在创建文件并且您提前知道要执行哪些类型的读取来访问数据,您可以使用它来创建行组。如果您不提前知道访问模式,或者您无法控制正在读取的文件的创建,那么您可能必须将整个文件读入内存并稍后进行过滤。

另一种常见情况是跨多个文件存储单个大型数据集(以便每个文件中都有一些行)。这允许您从多个行组中获得相同类型的部分读取行为。但是,拥有多个文件有时更易于管理。

pyarrow 和 fastparquet 都应该为您提供用于过滤行组的 API。它们还公开 parquet 文件元数据,以便您可以自己访问元数据信息以实现一些自定义过滤机制。

【讨论】:

以上是关于我可以通过索引访问 Parquet 文件而不将整个文件读入内存吗?的主要内容,如果未能解决你的问题,请参考以下文章

合并大文件而不将整个文件加载到内存中?

Actionscript 3,只能读取文件的一部分而不将整个文件加载到内存中

如何压缩整个文件夹(带有子文件夹)并通过 Flask 提供它而不将任何内容保存到磁盘

MatFile 对象仅支持 '()' 索引

从 MemoryStream 获取子字符串而不将整个流转换为字符串

从文本文件中读取第一行而不将整个文本文件加载到内存中