为什么在Apache Beam python中GroupByKey之后的FlatMap如此之慢?

时间:2017-08-25 21:28:05

标签: python google-cloud-dataflow apache-beam

鉴于密钥/值对的数据源相对较小(3,000-10,000),我试图仅处理满足组阈值(50-100)的记录。因此,最简单的方法是通过键,过滤和展开对它们进行分组 - 使用FlatMap或ParDo。到目前为止,最大的群体只有1,500条记录。但这似乎是Google Cloud Dataflow生产中的一个严重瓶颈。

给定列表

(1,1) (1,2) (1,3) ... (2,1) (2,2) (2,3) ...

运行一组转换以按键过滤和分组:

p | 'Group' >> beam.GroupByKey()
  | 'Filter' >> beam.Filter(lambda (key, values): len(list(values)) > 50)
  | 'Unwind' >> beam.FlatMap(lambda (key, values): values)

关于如何提高性能的任何想法?谢谢你的帮助!

1 个答案:

答案 0 :(得分:2)

这是管道的一个有趣的角落案例。我相信您的问题在于您阅读来自GroupByKey的数据的方式。让我简单介绍一下GBK的工作原理。

什么是GroupByKey,以及大数据系统如何实现它

所有大数据系统都实现了在同一密钥的多个元素上实现操作的方法。这在MapReduce中称为 reduce ,在其他大数据系统中称为Group By Key或Combine。

当您执行GroupByKey转换时,Dataflow需要将单个键的所有元素收集到同一台计算机中。由于可以在不同的机器中处理相同键的不同元素,因此需要以某种方式序列化数据。

这意味着当您读取来自GroupByKey的数据时,您正在访问工作者的IO(即不是来自内存),因此您确实希望避免多次读取随机数据。

这如何转换为您的管道

我认为您的问题是FilterUnwind都会分别从随机播放中读取数据(因此您将读取每个列表的数据两次)。你想要做的只是阅读你的shuffle数据一次。您可以使用单个FlatMap执行此操作,既可以过滤也可以展开您的数据,而无需从随机播放中重复读取。像这样:

def unwind_and_filter((key, values)):
  # This consumes all the data from shuffle
  value_list = list(values)
  if len(value_list) > 50:
    yield value_list

p | 'Group' >> beam.GroupByKey()
  | 'UnwindAndFilter' >> beam.FlatMap(unwind_and_filter)

如果有帮助,请告诉我。