如何加快批量导入多个工作人员的谷歌云数据存储?

时间:2018-05-07 01:15:42

标签: google-cloud-datastore google-cloud-dataflow apache-beam apache-beam-io

我有一个基于apache-beam的数据流作业,可以使用vcf source从单个文本文件(存储在Google云端存储中)中读取,将文本行转换为数据存储Entities并将其写入{{ 3}}。工作流程工作正常但我注意到的缺点是:

  • 数据存储区的写入速度最多约为每秒25-30个实体。
  • 我尝试使用--autoscalingAlgorithm=THROUGHPUT_BASED --numWorkers=10 --maxNumWorkers=100,但执行似乎更喜欢一个工人(见下图:目标工人曾经增加到2但减少到1"基于并行化工作的能力目前正在运行步骤")。

我没有使用祖先路径作为密钥;所有实体都是相同的kind

管道代码如下所示:

def write_to_datastore(project, user_options, pipeline_options):
"""Creates a pipeline that writes entities to Cloud Datastore."""
  with beam.Pipeline(options=pipeline_options) as p:
  (p
   | 'Read vcf files' >> vcfio.ReadFromVcf(user_options.input)
   | 'Create my entity' >> beam.ParDo(
     ToEntityFn(), user_options.kind)
   | 'Write to datastore' >> WriteToDatastore(project))

因为我有数百万行要写入数据存储区,所以用30个实体/秒的速度写入需要很长时间。

问题:输入只是一个巨大的gzip压缩文件。我是否需要将其拆分为多个小文件以触发多个工作人员?还有其他方法可以让导入速度更快吗?我是否遗漏了num_workers设置中的内容?谢谢!

2 个答案:

答案 0 :(得分:2)

我对apache beam不熟悉,答案来自一般流程的观点。

假设在各种输入文件部分中的实体数据之间没有依赖关系,那么是的,使用多个输入文件肯定会有所帮助,因为所有这些文件可以实际上并行处理(当然,取决于最大值)可用工人数量。)

可能不需要事先拆分巨大的zip文件,如果这种切换的开销,可能只需将单个输入数据流的各个部分切换到单独的数据段工作者进行写入与实际的数据段处理相比,它本身是不可忽视的。

整体性能限制将是读取输入数据的速度,将其拆分为段并切换到段数据工作者。

数据段工作人员将进一步将其接收的数据段拆分为较小的块,最多可相当于最多500个实体,这些实体可以转换为实体并在单个批处理操作中写入数据存储区。根据所使用的数据存储客户端库,可以异步执行此操作,允许拆分为块并转换为实体,而无需等待先前的数据存储写入完成。

数据段工作人员的性能限制将是数据段可以拆分成块并且块转换为实体的速度

如果异步操作不可用或吞吐量更高,则可以执行另一个块传递给段工作人员,段工作人员执行转换为实体和数据存储批量写入。

数据段工作者级别的性能限制将只是数据段可以拆分成块并移交给块工作者的速度。

通过这种方法,实际转换为实体并将它们批量写入数据存储区(异步与否)将不再处于拆分输入数据流的关键路径中,我认为,这是当前的性能限制方法

答案 1 :(得分:2)

我研究了vcfio的设计。我怀疑(如果我理解正确的话)当输入是单个文件时我总是得到一个工作者的原因是由于_VcfSourceVCF format约束的限制。此格式有一个标题部分,用于定义如何转换非标题行。这会导致每个读取源文件的worker必须处理整个文件。当我将单个文件拆分为共享相同标题的5个单独文件时,我成功地获得了5个工作人员(但由于同样的原因,这不是更多)。

我不明白的一件事是,阅读的工人数量可以限制为5(在这种情况下)。但为什么我们只限于只有5名工人写?无论如何,我认为我找到了使用梁Dataflow-Runner触发多个工作人员的替代方法(使用预拆分VCF文件)。 gcp variant transforms project中还有一种相关的方法,其中vcfio已得到显着扩展。它似乎通过单个输入vcf文件支持多个worker。我希望该项目的变化也可以合并到梁项目中。