web-dev-qa-db-ja.com

リデュースフェーズ後の出力ファイルのマージ

Mapreduceでは、各リデュースタスクはpart-r-nnnnnという名前のファイルに出力を書き込みます。ここでnnnnnはリデュースタスクに関連付けられたパーティションIDです。 map/reduceこれらのファイルをマージしますか?はいの場合、どのように?

74
Shahryar

自分でファイルのマージを行う代わりに、次を呼び出すことにより、reduce出力ファイルのマージ全体を委任できます。

hadoop fs -getmerge /output/dir/on/hdfs/ /desired/local/output/file.txt

これは、HDFSファイルをローカルに結合します。実行する前に十分なディスク容量があることを確認してください

117
diliop

いいえ、これらのファイルはHadoopによってマージされません。取得するファイルの数は、reduceタスクの数と同じです。

次のジョブの入力としてそれが必要な場合は、個別のファイルを用意する必要はありません。次のジョブの入力としてディレクトリ全体を指定するだけです。

クラスタ外のデータが必要な場合は、通常、データをクラスタからプルするときに受信側でそれらをマージします。

つまりこのようなもの:

hadoop fs -cat /some/where/on/hdfs/job-output/part-r-* > TheCombinedResultOfTheJob.txt
28
Niels Basjes

これは、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);
}
8
Mervyn

テキストファイルのみで、ソースと宛先の両方として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として設定します。

8
Gaurav Kumar

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

これがあなたの質問に答えることを願っています。

4
Aniruddha Sinha

追加のmap/reduceタスクを実行できます。mapおよびreduceはデータを変更せず、パーティショナーはすべてのデータを単一のreducerに割り当てます。

3
adamax

前回の回答に加えて、数分前に試みていたもう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つの出力ファイルを取得することは可能ですが、出力ファイルのサイズはプライマリメモリのサイズを超えてはなりません。つまり、出力ファイルは汎用マシンのメモリ出力ファイルの分割に関する問題。ありがとう!!

1
Aniruddha Sinha

ファイルにヘッダーがある場合、これを行うことでそれを取り除くことができます:

hadoop fs -cat /path/to/hdfs/job-output/part-* | grep -v "header" > output.csv

次に、output.csvのヘッダーを手動で追加します

0
Masih

パーティションファイルをマージするために、次のようなpigスクリプトを使用しないのはなぜですか。

stuff = load "/path/to/dir/*"

store stuff into "/path/to/mergedir"
0
Ian

。 map/reduceはこれらのファイルをマージしますか?

いいえ。マージされません。

IdentityReducer を使用して目標を達成できます。

すべての入力値を出力に直接書き込むことにより、削減を実行しません。

public void reduce(K key,
                   Iterator<V> values,
                   OutputCollector<K,V> output,
                   Reporter reporter)
            throws IOException

すべてのキーと値を出力に直接書き込みます。

関連するSEの投稿をご覧ください。

hadoop:0レデューサーとIDレデューサーの違い?

0
Ravindra babu