java—在hadoop中使用context.write()或outputcollector.collect()编写输出的成本?

cgfeq70w  于 2021-06-02  发布在  Hadoop
关注(0)|答案(1)|浏览(722)

我刚刚开始学习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 对象包含Map器根据某些过滤条件发出的大量记录,我需要将这些记录写入输出文件。或者,我也可以使用下面给定的方法。

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());
    }
}

不过,这两种方法在我的单节点设置上都可以很好地工作,用于多达400k条记录的大型输入数据集和 values 包含大约70k条记录的对象。我想问一下哪种方法更好?以及上面编写的代码在多节点集群上是否表现良好?谢谢你的帮助。谢谢。

yptwkmov

yptwkmov1#

最后,它总结了您写入的数据量(以字节为单位)。
这两种解决方案都有一定的大小开销,在第一个示例中,如果编写多个字符串,则序列化每个字符串的长度的开销是恒定的。在另一个解决方案中,写的开销与行分隔的开销相同。
因此,在字节大小上,两者都是相等的,因此在这两种解决方案中收集数据的速度不应明显减慢。
你的问题的一个非常不同的部分是内存使用,想想一个非常大的值迭代,你的 StringBuilder 将是低效的,因为调整大小的操作和它使用的所有内存。这个 collect 方法更智能,如果写入缓冲区已满,则会溢出到磁盘。另一方面,如果您有大量的可用内存,并且希望一次性写入一个巨大的记录,那么这可能与将写入缓冲区设置为类似大小一样有效。

相关问题