在Hadoop中使用context.write()或outputCollector.collect()编写输出的成本?

时间:2014-09-23 20:41:41

标签: java hadoop mapreduce processing-efficiency

我刚刚开始学习Hadoop,并且仍在尝试和尝试理解事物,我对OutputCollector类的collect()方法的用法非常好奇,我从现在开始的所有示例都只调用此方法一次。如果这个方法的调用成本非常高(因为它是将输出写入文件)?在思考不同场景时,我已经陷入了这样一种情况,即我发现需要不止一次地调用它。以下是明智的给定代码片段

public static class Reduce extends MapReduceBase implements
        Reducer<IntWritable, Text, Text, NullWritable> {
    public void reduce(IntWritable key, Iterator<Text> values,
            OutputCollector<Text, NullWritable> output, Reporter reporter)
            throws IOException {
        Text outData = null;
            while (values.hasNext()) {
                outData = new Text();
                outData.set(values.next().toString());
                output.collect(outData, NullWritable.get());
            }
    }
}

因为values对象包含大量记录,映射器根据某些过滤条件发出了这些记录,我需要将这些记录写入输出文件。反过来我也可以使用下面给出的方法

public static class Reduce extends MapReduceBase implements
        Reducer<IntWritable, Text, Text, NullWritable> {
    public void reduce(IntWritable key, Iterator<Text> values,
            OutputCollector<Text, NullWritable> output, Reporter reporter)
            throws IOException {
        StringBuilder sb = new StringBuilder();
        while (values.hasNext()) {
            sb.append(values.next().toString() + "\r\n ");
        }
        Text outData = new Text();
        outData.set(sb.toString());
        output.collect(outData, NullWritable.get());
    }
}

然而,对于包含大约70k记录的大型输入数据集和包含大约70k记录的values对象,这两种方法在我的单节点设置上都能正常工作。我想问一下哪种方法更好?上面编写的代码在多节点集群上也能表现得很好吗?任何帮助赞赏。感谢。

1 个答案:

答案 0 :(得分:2)

最后,它归结为您编写的数据量(以字节为单位)。

两个解决方案都有一些大小开销,在第一个示例中,您编写多个字符串,您需要经常序列化每个字符串的长度。在另一个解决方案中,您可以编写与行分隔相同的开销。

因此,在字节大小中,两者都是相等的,因此在两个解决方案中收集数据的速度不应该明显慢。

你的问题的一个非常不同的部分是内存使用,想到一个非常大的值迭代,由于调整大小操作和它使用的所有内存,你的StringBuilder将是低效的。如果写入缓冲区已填满,collect方法更智能并溢出到磁盘。另一方面,如果你有大量的可用内存并且你想一次写一个巨大的记录 - 这也可能与设置写缓冲区的大小相同。