来自PCollection的googledataflow/apachebeam Python端输入降低了性能
我们正在使用Python SDK在google数据流中运行日志文件解析作业。数据分布在数百个每日日志中,我们通过文件模式从云存储中读取这些日志。所有文件的数据量约为5-8GB(gz文件),共有5000-8000万行来自PCollection的googledataflow/apachebeam Python端输入降低了性能,python,google-cloud-dataflow,apache-beam,Python,Google Cloud Dataflow,Apache Beam,我们正在使用Python SDK在google数据流中运行日志文件解析作业。数据分布在数百个每日日志中,我们通过文件模式从云存储中读取这些日志。所有文件的数据量约为5-8GB(gz文件),共有5000-8000万行 loglines = p | ReadFromText('gs://logfile-location/logs*-20180101') 此外,我们还有一个简单的(小型)映射csv,它将日志文件条目映射到人类可读的文本。大约有400行,大小为5KB 例如,带有[param=testi
loglines = p | ReadFromText('gs://logfile-location/logs*-20180101')
此外,我们还有一个简单的(小型)映射csv,它将日志文件条目映射到人类可读的文本。大约有400行,大小为5KB
例如,带有[param=testing2]的日志文件条目应映射到最终输出中的“客户请求的14天免费产品试用”
我们在一个简单的beam.Map中使用sideinput进行此操作,如下所示:
customerActions = loglines | beam.Map(map_logentries,mappingTable)
mappingTable = p | ReadFromText('gs://side-inputs/category-mapping.csv')
customerActions = loglines | beam.Map(map_logentries,beam.pvalue.AsIter(mappingTable))
其中map_logentries是映射函数,mappingTable是映射表
但是,只有通过open()/read()读取本机python中的映射表时,这才有效。如果我们通过ReadFromText()使用梁管道执行相同操作,并将生成的PCollection作为侧面输入传递到地图,如下所示:
customerActions = loglines | beam.Map(map_logentries,mappingTable)
mappingTable = p | ReadFromText('gs://side-inputs/category-mapping.csv')
customerActions = loglines | beam.Map(map_logentries,beam.pvalue.AsIter(mappingTable))
性能完全分解为每秒2-3项
现在,我的问题是:
mappingTable
是一个映射,那么beam.pvalue.AsDict
不是更适合您的用例吗mappingTable
足够小,因此侧面输入是一个很好的用例。
鉴于mappingTable
也是静态的,您可以从您的DoFn
的start\u bundle
功能中的GCS加载它。有关更多详细信息,请参阅要发布的答案。如果<代码>映射表< /代码>将来变得非常大,您还可以考虑将“<代码> MAPyLogAccess < /COD>和<代码>映射表< /代码>转换为键值对的对于更有效的侧输入(小型到中型),您可以利用
beam.pvalue.AsList(映射表)
因为AsList
导致Beam具体化数据,所以您可以确定您将获得该pcollection的内存列表
用于侧边参数规范——相同位置
其中使用了Asingleton和AsIter,但强制实现
此PCollection作为列表
资料来源:
你说得对,
AsDict()
在这里更合适,但不会改变任何性能。我将更深入地查看您链接的帖子并尝试一下,这似乎是一个解决方案(重新使用映射表
)。我将在这里发布我的结果。好的,这基本上完成了我们现在正在做的工作,即在管道之外加载数据,然后在全局范围内重新使用它。唯一的区别是使用GCS API从GCS读取,如果我们坚持这个解决方案,这是一个很好的方法。但是,我认为使用管道本身是更自然的方法。您是否尝试过将mappingTable
与map\u logentries
与CoGroupByKey连接起来?这可能有点过分,但它允许您保持ReadFromText('gs://side inputs/category mapping.csv')
。在我的情况下,这不起作用,因为键(我们在其上执行映射)实际上可以在一行中出现多次(当然是不同的键)。因此,我必须乘以7000万行来重新设置它们的关键帧,然后再次“崩溃”。Marcin Zablocki指出了正确的方向:使用AsList()工作得非常好,我只是不明白为什么AsDict()或AsIter()不行。@SpiXel我对python beam SDK的经验有限。这两个start\u包都是side\u输入,应该是Java中可行的解决方案。但是,可能会多次调用start_bundle,尤其是对于流式管道。如果您尝试加载的数据很慢,这将影响您的性能。您能显示map_logentries的代码吗?在side input中使用AsList()时,您是否观察到相同的行为(性能差)?@MarcinZablocki:刚刚尝试使用AsList(),它的运行速度与我们的解决方法一样快。谢谢你!关于为什么AsList()比AsIter()或AsDict()好得多的任何解释/想法?我已经发布了我的答案谢谢-这解决了我的问题并解释了背后的原因。为什么实现PCollection会带来如此大的性能差异?即使是非物化的PCollection在从磁盘读取时也会被缓冲,因此问题不在于读取效率。也许问题在于它被一遍又一遍地读取,对于beam.Map
接收到的每一批都是一次?如果是这样,这种非缓存行为是由API规定的,还是一个实现细节?