我知道几周前对CDF服务进行了更新(默认工作人员类型和附加的PD已更改),并且很明显它会使批处理作业变慢。然而,我们的工作表现已经降低,超出了他们实际满足我们业务需求的程度。
例如,对于我们的一个特别工作:它从BigQuery中的表中读取~270万行,有6个侧输入(BQ表),执行一些简单的String转换,最后写入多个输出(3)到BigQuery的。过去需要5-6分钟,现在需要15-20分钟 - 无论我们查看多少VM。
我们能做些什么来让速度恢复到我们以前看到的水平?
以下是一些统计数据:
10个虚拟机(n1-standard-2) 16分5秒 2015-04-22_19_42_20-4740106543213058308
10个虚拟机(n1-standard-4) 17分11秒 2015-04-22_20_04_58-948224342106865432
10个虚拟机(n1-standard-1) 18分44秒 2015-04-22_19_42_20-4740106543213058308
20个虚拟机(n1-standard-2) 22分53秒 2015-04-22_21_26_53-18171886778433479315
50个虚拟机(n1-standard-2) 17分26秒 2015-04-22_21_51_37-16026777746175810525
100个虚拟机(n1-standard-2) 19分33秒 2015-04-22_22_32_13-9727928405932256127
答案 0 :(得分:4)
证据似乎表明管道如何处理侧输入存在问题。具体来说,对于主输入的每个元素,很可能一次又一次地从BigQuery重新读取侧输入。这与Dataflow工作人员使用的虚拟机类型的更改完全正交,如下所述。
这与Dataflow SDK for Java(版本0.3.150326)中所做的更改密切相关。在该版本中,我们更改了侧输入API以应用于每个窗口。对sideInput()
的调用现在仅在与主输入元素的窗口对应的特定窗口中返回值,而不是整个侧输入PCollectionView
。因此,无法再从sideInput()
的{{1}}和startBundle
调用finishBundle
,因为该窗口尚未知晓。
例如,以下代码片段存在一个问题,该问题会导致每个输入元素重新读取侧输入。
DoFn
通过在第一次调用@Override
public void processElement(ProcessContext c) throws Exception {
Iterable<String> uniqueIds = c.sideInput(iterableView);
for (String item : uniqueIds) {
[...]
}
c.output([...]);
}
期间将侧输入缓存到变换的List
成员变量(假设它适合内存),可以改进此代码,并使用缓存的{{1而不是后续调用中的侧输入。
此解决方法应该可以恢复之前看到的性能,此时可以从processElement
调用侧输入。从长远来看,我们将努力为侧面输入提供更好的缓存。 (如果这无法完全解决问题,请通过电子邮件与我们联系并分享相关的代码段。)
另外,确实有一个大约4/9/15的Cloud Dataflow Service更新,它更改了Dataflow工作人员使用的默认虚拟机类型。具体来说,我们减少了每个工作者的默认核心数,因为我们的基准测试显示它对于典型的工作来说是经济有效这是不在任何类型的数据流服务中的减速 - 默认情况下,它只是以每个工作者的较少资源运行。用户仍然可以选择覆盖工作人员数量以及工作人员使用的虚拟机类型。
答案 1 :(得分:2)
我们追查了这个问题。当侧输入从已经将数据流入的BigQuery表中读取而不是批量加载时。当我们复制表格并从副本中读取时,一切正常。
但是,这只是一种解决方法。 Dataflow应该能够处理BigQuery中的流表作为侧输入。