如何使用 Parquet.net 从 Parquet 文件中仅读取列的一部分?

Posted

技术标签:

【中文标题】如何使用 Parquet.net 从 Parquet 文件中仅读取列的一部分?【英文标题】:How do I read only part of a column from a Parquet file using Parquet.net? 【发布时间】:2020-11-10 07:49:50 【问题描述】:

我正在使用 Parquet.Net 读取 parquet 文件,但从 parquet 文件中读取的唯一选项是。

//get the first group
Parquet.ParquetRowGroupReader rowGroup = myParquet.OpenRowGroupReader(0);

//gets the first column
Parquet.Data.DataColumn col1 = rowGroup.ReadColumn(myParquet.Schema.GetDataFields()[0]);

这允许我从第一个 rowGroup 中获取第一列,但问题是,第一个 rowGroup 可能是 400 万行,而 readColumn 将读取所有 400 万个值。

我如何告诉 readColumn 我只希望它读取,比如前 100 行。读取全部 400 万行会浪费内存和文件读取时间。

我实际上遇到了内存错误,直到我更改代码以将 400 万值数组的大小调整为我的 100。在调用每一列之后。

我不一定需要基于行的访问,我可以使用列,我只是不需要每列中的整个 rowGroup 值。这可能吗?如果基于行的访问更好,如何使用它? Parquet.Net 项目网站没有给出任何示例,只是谈论表格。

【问题讨论】:

【参考方案1】:

根据源代码,此功能存在于 DataColumnReader 中,但这是一个 internal 类,因此不能直接使用。

ParquetRowGroupReader 在其 ReadColumn 方法中使用它,但没有公开此类选项。

在实践中可以做的是复制整个DataColumnReader 类并直接使用它,但这可能会滋生未来的兼容性问题。

如果问题可以等待一段时间,我建议复制该类,然后使用增强类向库打开一个问题 + 拉取请求,这样最终可以删除复制的类。

【讨论】:

谢谢,我通过吃问题中的读取时间和内存使用来做到了。如果我需要再次处理我的项目(可能永远不会),我会尝试的!但我不熟悉打开问题和提出拉取请求等,也不熟悉,所以......其他人可能会在我之前做这件事。【参考方案2】:

如果您查看parquet-dotnet documentation,出于性能原因,他们不建议将超过 5000 条记录写入一个行组,尽管在页面底部他们说它们旨在平均容纳 50000 行:

不建议在单行中包含超过 5'000 行 出于性能原因分组

我们正在与我的团队在一个行组中处理 100000 条记录,总体而言,这可能取决于您存储的内容,但在一列中的一个行组中的 4000000 条记录听起来太多了。

因此,为了回答您的问题,只读取列的一部分使列内的行组更小,然后只读取您希望的任意数量的行组。如果您只想读取 100 条记录,则在第一个行组中读取并从中取出前 100 条,合理大小的行组读取速度非常快。

【讨论】:

1) 您假设我们正在编写这些文件,而不是其他人。 2)即使数据被分成更小的行组,如何在不读取每个行组的整列的情况下找到列值在所需范围内的行组? 1) 是的,如果您无法控制行组的大小,那么 parquet.net 可能不是用于读取这些文件的正确库 2) 相同,我不认为您可以用 parquet.net 做到这一点,也许看看 Spark 或其他 parquet 阅读选项,目前可能无法使用 .Net 这真的很奇怪。实施起来并不难。 我认为这可能是因为 Parquet 格式是一种基于列的格式,它大量使用压缩来节省存储空间,列包含行组但我认为它们可能与它们自己的元数据一起被压缩,所以在完全解压缩之前,行组可能无法读取?我不完全理解格式是如何工作的。尽管如此,也许上面提到的 DataColumnReader 有一种方法可以逐行读取它。

以上是关于如何使用 Parquet.net 从 Parquet 文件中仅读取列的一部分?的主要内容,如果未能解决你的问题,请参考以下文章

Sqooping 数据后 Hive 抛出错误

使用带有 Oozie 的 sqoop 观察重复项

将 Parquet 数据加载到 PIG 时如何避免 UnsatisfiedLinkError

如何使作业幂等于多次运行在S3中生成相同的结果文件

大数据:ClickHouse-HDFS集成

使用 Python 编写 Parquet 文件的方法?