使用Dask高效地从Blob存储中读取Parquet文件的部分列

3
我该如何高效地读取托管在云 Blob 存储(例如 S3 / Azure Blob 存储)中的 parquet 文件的部分列呢? parquet 文件格式的列式结构是其关键优势之一,因此选择性地读取列可以减少 I/O 负载。将数据存储在 Blob 存储中以在云上运行大规模工作负载也是很自然的。但是,一旦将 parquet 文件存储为 Blob,大多数库(dask、fastparquet、pyarrow)实际上无法利用它,因为底层的 fseek 不能直接在 Blob 上进行 - 这意味着无论选择哪些列,都必须先将整个文件下载到本地文件系统中才能读取。
因此,如果我的用例需要不同的应用程序需要不同的列,并且仅为了几列而下载整个文件的性能成本是不可接受的,那么最佳实践是什么?我应该为每个列存储不同的 parquet 文件,同时使用 pandas/dask 等在应用程序级别进行合并吗?Apache Parquet 格式是否具有通过列拆分数据集的内置支持 - 类似于 Hive 格式按分区划分然后按分区划分?
感谢任何帮助/使用 dask 或 fastparquet 的具体示例。
1个回答

3

(fsspec和fastparquet的作者撰写)

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

即使是类似键值对(如azure blob和datalake、s3、gcsfs)的后端存储,仍然支持范围请求,这意味着工作进程仅下载感兴趣的字节。

但是,还有一些细微之处。与磁盘相比,远程存储的延迟(首字节时间)要高得多,因此数据吞吐量严重依赖于所发出的请求数:在文件中搜索会具有可变效率,这取决于所采用的预读/缓存策略。您可以使用storage_options参数来微调此行为。

否,没有特别支持将列分别存储,尽管在相同索引上进行连接通常应该是高效的。但通常不需要这样做,更重要的是其他考虑因素,例如使用正确的数据类型和分区大小。这些事情通常是基于情况而定,并且您特定数据存储的延迟可能是一个重要因素。

请还参见https://github.com/fsspec/filesystem_spec/issues/885,了解专门针对parquet数据的fsspec缓存方案。


你提到了细微之处和特定情况。你能否对什么时候它只会读取所选列中的数据给出更明确的说明?或者基本上它总是这样做,只是需要知道会有一些延迟作为结果? - undefined
1
我添加了一些相关细节。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接