如何控制pyarrow.dataset.write_dataset是覆盖之前的数据还是追加?

How to control whether pyarrow.dataset.write_dataset will overwrite previous data or append to it?

我正在尝试使用 pyarrow.dataset.write_dataset 函数将数据写入 hdfs。但是,如果我写入一个已经存在并有一些数据的目录,数据将被覆盖,而不是创建一个新文件。有没有一种方法可以方便地“附加”到已经存在的数据集,而不必先读入所有数据?我不需要数据在一个文件中,我只是不想删除旧的。

我目前做什么和不做什么:

import pyarrow.dataset as ds
parquet_format = ds.ParquetFileFormat()
write_options = parquet_format.make_write_options(
use_deprecated_int96_timestamps = True,
coerce_timestamps = None, 
allow_truncated_timestamps = True)
ds.write_dataset(data = data, base_dir = 'my_path', filesystem = hdfs_filesystem, format = parquet_format, file_options = write_options)

目前,write_dataset 函数使用固定的文件名模板(part-{i}.parquet,其中 i 是一个计数器,如果您正在写入多个批次;如果写入单个 Table i 永远是 0).

这意味着当多次写入同一目录时,如果这些文件名为 part-0.parquet.

,它确实可能会覆盖先前存在的文件

解决这个问题的方法是确保 write_dataset 通过 basename_template 参数为每​​次写入使用唯一的文件名,例如:

ds.write_dataset(data=data, base_dir='my_path',
                 basename_template='my-unique-name-{i}.parquet', ...)

如果您想在每次写入时自动拥有一个唯一的名称,您可以生成一个随机字符串以包含在文件名中。一种选择是使用 python uuid stdlib 模块:basename_template = "part-{i}-" + uuid.uuid4().hex + ".parquet"。 另一种选择是在文件名中包含当前写入时间以使其唯一,例如 basename_template = "part-{:%Y%m%d}-{{i}}.parquet".format(datetime.datetime.now())

https://issues.apache.org/jira/browse/ARROW-10695 for some more discussion about this (customizing the template), and I opened a new issue specifically about the issue of silently overwriting data: https://issues.apache.org/jira/browse/ARROW-12358

对于那些来这里了解如何将 make_write_options()write_dataset 结合使用的人,试试这个:

import pyarrow.dataset as ds
parquet_format = ds.ParquetFileFormat()
write_options = parquet_format.make_write_options(use_deprecated_int96_timestamps = False, coerce_timestamps = 'us', allow_truncated_timestamps = True)