2014-09-23 112 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

相關問題