鉴于密钥/值对的数据源相对较小(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)
关于如何提高性能的任何想法?谢谢你的帮助!
答案 0 :(得分:2)
这是管道的一个有趣的角落案例。我相信您的问题在于您阅读来自GroupByKey
的数据的方式。让我简单介绍一下GBK的工作原理。
GroupByKey
,以及大数据系统如何实现它所有大数据系统都实现了在同一密钥的多个元素上实现操作的方法。这在MapReduce中称为 reduce ,在其他大数据系统中称为Group By Key或Combine。
当您执行GroupByKey
转换时,Dataflow需要将单个键的所有元素收集到同一台计算机中。由于可以在不同的机器中处理相同键的不同元素,因此需要以某种方式序列化数据。
这意味着当您读取来自GroupByKey
的数据时,您正在访问工作者的IO(即不是来自内存),因此您确实希望避免多次读取随机数据。
我认为您的问题是Filter
和Unwind
都会分别从随机播放中读取数据(因此您将读取每个列表的数据两次)。你想要做的只是阅读你的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)
如果有帮助,请告诉我。