使用 pyspark 从 s3 缓慢读取 500k 小 parquet 文件

问题描述 投票:0回答:1

我一直在开发一个转换系统,其源是存储在 s3 中的大量小 parquet 文件(~150 KB)。当我尝试使用

spark.read.parquet(*keys)
在 pyspark 作业中读取这些文件时,需要花费很多时间。对于 40CPU 集群来说,仅读取一次就需要大约 1 小时。所有这些镶木地板文件都具有相同的架构。

在四处搜索时,我遇到了“spark 小文件”问题。所以我尝试实现一个压缩器,它可以预读取这些镶木地板文件,重新分区它们并保留在 PVC 上。即使采用这种方法,我仍然面临压实机的较长读取时间。

为了将文件从 s3 获取到本地 PVC,我尝试创建一个 Spark 作业,使用 Boto3 客户端下载密钥,并稍后下载它们进行压缩,以便我的转换工作会很快。我使用 boto3 客户端获得的下载速度明显快于读取操作。

还有其他优化的方式来读取这些文件吗?或者我应该使用 Spark boto3 将这些文件下载到 PVC,然后编写一个实用程序来压缩它们。

更新: 我正在测试的实际实例是 MinIO 实例。 键前缀包含我也需要读取的元数据。 示例:{bucket_name}/{metadata1=abc}/{metadata2=abc}/{metadata3=abc}/data.parquet

apache-spark amazon-s3 pyspark boto3 parquet
1个回答
1
投票

Parquet 查询在云上并不是最优的,因为eek() 操作会强制执行多个 GET 请求(页脚、模式、范围...)。最好使用任何查询的最后阶段将文件合并为少量较大的文件。正如您所注意到的:将所有文件拉到单个本地主机(每个文件一个 GET),合并并写入那里可能是最有效的。

单个 s3 分区的每秒读取次数被限制为 5000 次,因此在遇到限制之前,在 parquet 读取上发出的多个 GET 请求很可能会限制您每秒处理 1500 个文件。这将触发指数睡眠和退避,因此会严重损害吞吐量。

在本地下载时,需要付出努力才能生成这 5000 次读取,尽管在 EC2 中这是可能的。考虑使用某种速率限制器(例如谷歌番石榴)来阻止读取低于阈值。

最后,每个文件的目标是 256MB 或更多。这是列出/读取文件的开销变得不那么重要的地方。

对于任何对云中的 ORC/Parquet IO 感兴趣的人,请参阅:列式存储格式的实证评估

© www.soinside.com 2019 - 2024. All rights reserved.