![](/img/trans.png)
[英]Problem with using collect() function of DataSet in apache flink
[英]Avoid using a collect on large dataset
我们使用 Apache Spark 进行处理。 我们有几个步骤需要使用 collect() 将 JavaRDD 转换为列表,但为了对列表进行操作,我们希望避免这样做。 我们知道我们想要避免这种情况,因为它会将所有内容都带回给驱动程序。 它最终会耗尽内存,因为我们正在处理 500 万到 2 亿条记录。 这是迄今为止我们所拥有的一个例子。
private InputStream createCSVObject(JavaRDD<Object[]> args) {
System.out.println("inside createCSVObject");
try {
StringBuilder value = new StringBuilder(CHUNK_SIZE);
args.collect().forEach(i -> {
value.append(i[0].toString());
for (int j = 1; j < i.length; ++j) {
value.append("," + i[j]);
}
value.append("\n");
});
System.out.println("Out of createCSVObject for loops");
byte[] strBytes = value.toString().getBytes();
InputStream myInputStream = new ByteArrayInputStream(strBytes);
return (myInputStream);
} catch (Exception e) {
System.err.println(String.format("ERROR: FileWriterService - writeFile: %s", e.getMessage()));
return null;
}
}
我已经在 SO 和 google 上一遍又一遍地搜索了这个,但找不到任何确定的东西。 有没有人有任何想法???
注意:args.collect() 中的 COLLECT
编辑:
在查看下面建议的答案后,我们为其设计了一个简单的概念证明,我们提出的方法每 40 秒迭代一次。 逻辑不复杂,为什么这么慢?
System.out.println("inside createCSVObject");
try {
StringBuilder value = new StringBuilder();
System.out.println("args length " + args.toLocalIterator().next().length);
while (args.toLocalIterator().hasNext()) {
Object[] objects = args.toLocalIterator().next();
System.out.println("Inside iterator");
value.append(objects[0].toString());
for (int j = 1; j < objects.length; ++j) {
value.append("," + objects[j]);
}
value.append("\n");
}
System.out.println("Out of createCSVObject for loops");
byte[] strBytes = value.toString().getBytes();
InputStream myInputStream = new ByteArrayInputStream(strBytes);
return (myInputStream);
} catch (Exception e) {
System.err.println(String.format("ERROR: FileWriterService - writeFile: %s", e.getMessage()));
e.printStackTrace();
return null;
}
您可以使用JavaRDD.toLocalIterator()
遍历驱动程序上的整个 RDD,而无需将其全部收集到列表中。 相反,它将每个分区一次一个地交给驱动程序,因此不会使用比最大分区大小更多的内存( 文档)。
显然,在您给出的示例中,您仍然存在将所有内容收集到一个庞大的字节数组中的问题,该数组仍将使用相当多的内存。 相反,您可以编写一个自定义InputStream
类来包装Iterator
(由toLocalIterator
返回),并且一次仅缓冲一个元素,仅当InputStream.read()
需要更多数据时才在迭代器上调用next()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.