使用 dask 高效地只读取 blob 存储上镶木地板文件中的某些列

Efficiently reading only some columns from parquet file on blob storage using dask

如何才能有效地只读取云 blob 存储(例如 S3/Azure Blob 存储)中托管的 parquet 文件的某些列?

列式结构是 parquet 文件格式的主要优势之一,因此有选择地读取列可以减少 I/O 负载。对于云上的 运行 大规模工作负载,将数据存储在 blob 存储中也很自然。但是,一旦 parquet 文件存储为 blob,大多数库(dask、fastparquet、pyarrow)就无法真正利用这一点,因为底层 fseek 不可能直接在 blob 上实现——这意味着无论选择了哪些列,在读取之前必须将整个文件下载到本地文件系统。

因此,如果我的用例是单独的应用程序需要不同的列,并且仅下载几列的整个文件的性能成本是不可接受的,那么最佳做法是什么?我是否应该为每一列存储不同的镶木地板文件以及一个公共索引,然后使用 pandas/dask 等在应用程序级别合并? apache parquet 格式是否有一些内置支持按列拆分数据集 - 类似于 hive 格式如何按分区然后按分区拆分?

感谢任何使用 dask 或 fastparquet 的帮助/具体示例。

(fsspec 和 fastparquet 写作的作者)

简短回答:是的,Dask 读取 parquet 将 select 仅从远程存储中读取您需要的列,并且在某些情况下只能读取整个数据集中的部分分区。如果您事先知道,最好在调用 read_parquet 时定义 columns= 的集合,但 Dask 会尝试从您的计算图中推断出正确的值;例如,dd.read_parquet(...).column1.compute() 只会获取“column1”。对于更复杂的计算,这种推断可能会失败。

后端存储,即使像(azure blob 和 datalake、s3、gcsfs)这样的键值对,仍然支持范围请求,这意味着工作人员只下载感兴趣的字节。

然而,有一些微妙之处。与磁盘相比,远程存储将有更高的延迟(到第一个字节的时间),因此数据吞吐量在很大程度上取决于请求的数量男性:寻找文件的效率会有所不同,具体取决于 read-ahead/caching采用的策略。您可以使用 storage_options 参数来微调此行为。

不,没有特别支持单独存储列,尽管连接相同的索引通常应该是有效的。但是,这通常不是必需的,更重要的是其他考虑因素,例如要使用的正确数据类型和分区大小。这些事情通常取决于具体情况,您的特定数据存储的延迟可能是一个重要因素。

另请参阅 https://github.com/fsspec/filesystem_spec/issues/885 以了解专为 parquet 数据量身定制的 fsspec 缓存方案。