首页 > 解决方案 > 在分区日期集上使用 Dask 时 _metadata 文件的重要性

问题描述

我有一个简单的理解,即可以将有关 parquet 数据集中文件的信息放入_metadata文件中,并用于更有效地创建 parquet Datasetto_parquet但是,在将 Dask与append=Trueand一起使用时,我遇到了性能问题write_metadata_file=True,我的完整命令如下。(我还没有完全理解发生了什么,但我的记忆会飙升,就在to_parquet被拆分给工人之前)。因此,我决定在write_metadata_file=False没有文件的情况下设置并继续_metadata,删除之前创建的_metadata文件。

我发现问题消失了,而且to_parquet速度也没有变慢,如果有的话,我节省了时间,不必_metadata每次都写文件。

另外一目了然,当我read_parquet打开文件时,似乎没有_metadata文件并没有像我预期的那样导致性能不佳。

我在追加时选择了分区,想知道这是否是_metadata文件不那么重要的原因,还是不正确?_metadata是否存在文件重要和不重要的明显情况?

简单的代码示例

dd.to_parquet(df,
              engine='fastparquet',
              path=uri, storage_options=dl.storage_options,
              partition_on=['A', 'B', 'C'],
              append=True,
              ignore_divisions=True,
              write_metadata_file=False)

标签: pythondask

解决方案


元数据文件提供了三个可能有用的东西:

  • 所有组成分区的文件名
  • 列块的每个文件中的偏移量
  • 每个列块内的值的最小/最大统计信息
  • 可以从 _common_metadata 文件或任何一个数据文件中读取数据集的模式。

通过列出文件系统很容易找到其中的第一个,它在本地速度很快,但如果您有数千个文件,远程存储可能会很慢。

第二个是必需的,但可以从每个数据文件的页脚、工作任务和并行读取。因此,如果你没有提前得到它们,你最终会做更多的工作,但可能不会注意到(特别是如果每​​个部分都有很多行)。与在客户端解析巨大的元数据文件相比,它最终可能会更快。

第三,如果不是从元数据文件中获取,只能通过扫描所有文件的元数据页脚来获取,这可能会非常缓慢并且在客户端单线程完成。但是,如果您不使用这些统计信息进行过滤(gather_statistics=None 或 False),那么您完全可以不用。您仍然可以在没有最大/最小统计信息的情况下过滤分区列。

最后,为了完整性:为什么分区附加元数据很慢?每次追加时都必须重写单个元数据文件,并且它首先需要从每个任务中获取所有元数据片段。我还需要将所有元数据片段保存在内存中。这可能会做得更好,但这是当前的实现。


推荐阅读