2

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

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

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

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

4

1 回答 1

3

(fsspec 和 fastparquet 写作的作者)

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

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

然而,也有一些微妙之处。与磁盘相比,远程存储的延迟(第一个字节的时间)要高得多,因此数据吞吐量在很大程度上取决于男性请求的数量:在文件中查找将具有可变的效率,具体取决于预读/缓存采用的策略。您可以使用该storage_options参数来微调此行为。

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

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

于 2019-12-02T14:42:07.717 回答