首页 > 解决方案 > 读取 S3 parquet 表的最后 N 行

问题描述

如果我将此处讨论的内容应用于将 S3 buck 中的镶木地板文件读取到 pandas 数据帧,尤其是:

import pyarrow.parquet as pq
import s3fs
s3 = s3fs.S3FileSystem()

pandas_dataframe = pq.ParquetDataset('s3://your-bucket/', filesystem=s3).read_pandas().to_pandas()

当表随着时间的推移变得越来越大并且我需要定期进行此检索时,我只想将最后 N 行读入数据框中。这可能吗?

标签: pythonamazon-web-servicesamazon-s3pyarrow

解决方案


是的,这是完全可能的。S3 允许部分对象读取。Parquet 文件允许基于行组的部分读取(并且 pyarrow 公开了此功能)。此外,如果您有多个文件(无论文件格式如何),pyarrow 允许部分读取。但是,这些方法将对如何创建输入文件提出一些要求(请参阅底部的旁注)。

简单的方法

最简单的事情是使用较新的数据集 API(它本身值得一读,并且废弃了您引用的一些问题)并在某种列上进行过滤。

import pyarrow.dataset as ds
from datetime import datetime, timedelta

two_days_ago = datetime.now() - timedelta(days=2)
dataset = ds.dataset('s3://your-bucket').to_table(filter=ds.field('sample_date') > two_days_ago)

pyarrow datasets API 支持“下推过滤器”,这意味着过滤器被下推到阅读器层。如果阅读器能够减少使用过滤器读取的数据量,那么它会。对于像这样的简单过滤器,镶木地板阅读器能够通过首先查看行组元数据来优化读取,该行组元数据应该有一个“统计”部分,其中包含每列的最小值/最大值。

但是,这并不完全是“最后 N 行”,因为它需要您制作某种过滤器。如果您可以完全控制数据,那么您可以创建一个row_num列。如果您知道总行数(您可以单独存储或通过元数据访问,请参见下文),则可以在其上创建一个过滤器。

稍微不那么简单的方法

或者,您可以使用ParquetFilewhich 具有该metadata属性。访问它只会触发对元数据本身(不是整个文件)的读取。从中您可以获得一些信息,例如文件中有多少行组以及它们包含多少行。您可以使用它来确定您需要多少行组,并且您可以使用read_row_groupread_row_groups仅访问这些行组(这不会触发完整的文件读取)。

这些解决方案都不是理想的。第一个选项要求您对数据有更多的控制权,而第二个选项要求您自己做很多工作。Arrow 项目正在努力简化此类操作(例如,参见ARROW-3705)。但是,此答案仅基于当今可用的功能。

最后一点:所有这些方法(甚至是 Arrow 开发的任何未来方法)都需要将数据存储为多个文件或多个行组。如果您将一个巨大的文件存储为单个行组,那么可以做的事情不多。Parquet 不支持部分行组读取。


推荐阅读