Mapreduceでは、各リデュースタスクはpart-r-nnnnnという名前のファイルに出力を書き込みます。ここでnnnnnはリデュースタスクに関連付けられたパーティションIDです。 map/reduceこれらのファイルをマージしますか?はいの場合、どのように?
自分でファイルのマージを行う代わりに、次を呼び出すことにより、reduce出力ファイルのマージ全体を委任できます。
hadoop fs -getmerge /output/dir/on/hdfs/ /desired/local/output/file.txt
注これは、HDFSファイルをローカルに結合します。実行する前に十分なディスク容量があることを確認してください
いいえ、これらのファイルはHadoopによってマージされません。取得するファイルの数は、reduceタスクの数と同じです。
次のジョブの入力としてそれが必要な場合は、個別のファイルを用意する必要はありません。次のジョブの入力としてディレクトリ全体を指定するだけです。
クラスタ外のデータが必要な場合は、通常、データをクラスタからプルするときに受信側でそれらをマージします。
つまりこのようなもの:
hadoop fs -cat /some/where/on/hdfs/job-output/part-r-* > TheCombinedResultOfTheJob.txt
これは、HDFSでファイルをマージするために使用できる機能です
public boolean getMergeInHdfs(String src, String dest) throws IllegalArgumentException, IOException {
FileSystem fs = FileSystem.get(config);
Path srcPath = new Path(src);
Path dstPath = new Path(dest);
// Check if the path already exists
if (!(fs.exists(srcPath))) {
logger.info("Path " + src + " does not exists!");
return false;
}
if (!(fs.exists(dstPath))) {
logger.info("Path " + dest + " does not exists!");
return false;
}
return FileUtil.copyMerge(fs, srcPath, fs, dstPath, false, config, null);
}
テキストファイルのみで、ソースと宛先の両方としてHDFSの場合、以下のコマンドを使用します。
hadoop fs -cat /input_hdfs_dir/* | hadoop fs -put - /output_hdfs_file
これにより、input_hdfs_dir
のすべてのファイルが連結され、output_hdfs_file
でHDFSに出力が書き戻されます。すべてのデータがローカルシステムに戻されてから再びhdfsにアップロードされますが、一時ファイルは作成されず、UNIX peを使用してその場で発生することに注意してください。
また、これはAvro、ORCなどの非テキストファイルでは機能しません。
バイナリファイルの場合、次のようなことができます(ディレクトリにマップされたHiveテーブルがある場合)。
insert overwrite table tbl select * from tbl
構成によっては、これによりファイル以外のものも作成される場合があります。単一のファイルを作成するには、mapreduce.job.reduces=1
を使用してリデューサーの数を明示的に1に設定するか、HiveプロパティをHive.merge.mapredfiles=true
として設定します。
Part-r-nnnnnファイルは、間に「r」で指定された削減フェーズの後に生成されます。事実、1つの減速機を実行している場合、part-r-00000のような出力ファイルが作成されます。レデューサーの数が2の場合、part-r-00000とpart-r-00001などがあります。 hadoopフレームワークはCommodity Machinesで実行するように設計されているため、出力ファイルが大きすぎてマシンのメモリに収まらない場合、ファイルは分割されます。 MRv1に従って、ロジックで動作するリデューサーは20個に制限されています。構成ファイルでカスタマイズする必要があるものはもっとありますが、同じ必要がありますmapred-site.xml。あなたの質問について話す; getmergeを使用するか、次のステートメントをドライバーコードに埋め込んでレデューサーの数を1に設定します。
job.setNumReduceTasks(1);
これがあなたの質問に答えることを願っています。
追加のmap/reduceタスクを実行できます。mapおよびreduceはデータを変更せず、パーティショナーはすべてのデータを単一のreducerに割り当てます。
前回の回答に加えて、数分前に試みていたもう1つの回答があります。 CustomOutputFormatを使用できます。これは以下のコードのようになります
public class VictorOutputFormat extends FileOutputFormat<StudentKey,PassValue> {
@Override
public RecordWriter<StudentKey,PassValue> getRecordWriter(
TaskAttemptContext tac) throws IOException, InterruptedException {
//step 1: GET THE CURRENT PATH
Path currPath=FileOutputFormat.getOutputPath(tac);
//Create the full path
Path fullPath=new Path(currPath,"Aniruddha.txt");
//create the file in the file system
FileSystem fs=currPath.getFileSystem(tac.getConfiguration());
FSDataOutputStream fileOut=fs.create(fullPath,tac);
return new VictorRecordWriter(fileOut);
}
}
ちょうど、最後から4行目を見てください。出力ファイル名として自分の名前を使用し、15個の減速機でプログラムをテストしました。それでもファイルは同じままです。したがって、2つ以上ではなく1つの出力ファイルを取得することは可能ですが、出力ファイルのサイズはプライマリメモリのサイズを超えてはなりません。つまり、出力ファイルは汎用マシンのメモリ出力ファイルの分割に関する問題。ありがとう!!
ファイルにヘッダーがある場合、これを行うことでそれを取り除くことができます:
hadoop fs -cat /path/to/hdfs/job-output/part-* | grep -v "header" > output.csv
次に、output.csvのヘッダーを手動で追加します
パーティションファイルをマージするために、次のようなpigスクリプトを使用しないのはなぜですか。
stuff = load "/path/to/dir/*"
store stuff into "/path/to/mergedir"
。 map/reduceはこれらのファイルをマージしますか?
いいえ。マージされません。
IdentityReducer を使用して目標を達成できます。
すべての入力値を出力に直接書き込むことにより、削減を実行しません。
public void reduce(K key,
Iterator<V> values,
OutputCollector<K,V> output,
Reporter reporter)
throws IOException
すべてのキーと値を出力に直接書き込みます。
関連するSEの投稿をご覧ください。