2014-09-23 114 views
1

我刚刚开始学习Hadoop,并且仍在试验和尝试理解事情,我对OutputCollector类collect()方法的使用非常好奇,因为现在我发现的所有示例都只调用一次该方法。如果这种方法的调用成本非常高(因为它将输出写入文件)?同时考虑到我遇到的情况不同,我发现需要多次调用它。像明智下面是给定的代码段在Hadoop中使用context.write()或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对象包含大量的其映射器根据一些过滤条件已经发出记录和我需要编写这些记录到输出file.OR周围的其他方法我也可以使用下面给出的方法。

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

但是这两种方法适用于我的singlenode设置为大的输入细数据集的高达40万条记录,并含有约70K的记录values对象。我想问问哪种方法更好?以及上面的书面代码在多节点集群上的表现还会好吗?任何帮助赞赏。谢谢。

回答

2

最后,它会确定您写入的数据量(以字节为单位)。

这两种解决方案都有一定的开销,在第一个例子中你写了多个字符串,你有不断的串行化每个字符串长度的开销。在另一种解决方案中,您写入与线路分隔相同数量的开销。

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

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

+0

感谢@Thomas,所以根据collect方法的功能,在这种写入Mb或更多数据的场景中,它似乎更有效率。 – 2014-09-24 06:00:04

+1

是的,但这确实是一个普遍的建议,并且hadoop会照顾不会泄漏一个小缓冲区。 – 2014-09-24 07:17:20

+0

好的,非常感谢。 – 2014-09-24 07:21:28

相关问题