0

削減フェーズの削減プログラムで MultipleOutputs を使用しています。私が取り組んでいるデータ セットは約 270 mb で、擬似分散単一ノードでこれを実行しています。マップの出力値に書き込み可能なカスタムを使用しました。キーはデータセットに存在する国です。

public class reduce_class extends Reducer<Text, name, NullWritable, Text> {
    public void reduce(Text key,Iterable<name> values,Context context) throws IOException, InterruptedException{
        MultipleOutputs<NullWritable,Text> m = new MultipleOutputs<NullWritable,Text>(context);
        long pat;
        String n;
        NullWritable out = NullWritable.get();
        TreeMap<Long,ArrayList<String>> map = new TreeMap<Long,ArrayList<String>>();
        for(name nn : values){
            pat = nn.patent_No.get();
            if(map.containsKey(pat))
                map.get(pat).add(nn.getName().toString());
            else{
                map.put(pat,(new ArrayList<String>()));
                map.get(pat).add(nn.getName().toString());}
    }
        for(Map.Entry entry : map.entrySet()){
            n = entry.getKey().toString();
            m.write(out, new Text("--------------------------"), key.toString());
            m.write(out, new Text(n), key.toString());
            ArrayList<String> names = (ArrayList)entry.getValue();
            Iterator i = names.iterator();
            while(i.hasNext()){
                n = (String)i.next();
                m.write(out, new Text(n), key.toString());
        }
            m.write(out, new Text("--------------------------"), key.toString());           
    }
        m.close();
}

}

上記は私の削減ロジックです

問題

1) 上記のコードは小さなデータ セットでは問題なく動作しますが、270 MB のデータ セットではヒープ スペースが原因で失敗します。

2) 国をキーとして使用すると、単一の反復可能なコレクションでかなり大きな値が渡されます。これを解決しようとしましたが、MutlipleOutputs は特定のキー セットに対して一意のファイルを作成します。ポイントは、以前のreduceの実行によって作成された既存のファイルを追加できず、エラーがスローされることです。したがって、特定のキーについては、新しいファイルを作成する必要があります。これを回避する方法はありますか? . 上記のエラーを解決すると、キーを国名 (最終的に並べ替えられたデータ) として定義することになりましたが、Java heap error がスローされます。

サンプル入力

3858241,"Durand","Philip","E.","","","Hudson","MA","US","",1 3858241,"Norris","Lonnie","H. ","","","ミルフォード","マサチューセッツ州","US","",2 3858242,"グッディング","エルウィン","R.","","120 ダーウィン ロード"," Pinkney","MI","US","48169",1 3858243,"Pierron","Claude","Raymond","","","エピナル","","FR","", 1 3858243,"ジェニー","ジャン","ポール","","","デシネス","","FR","",2 3858243,"ズッカロ","ロバート",""," "、"","エピナル","","FR","",3 3858244,"マン","リチャード","L.","","PO Box 69","ウッドストック","CT"," US","06281",1

小さなデータセットの出力例

サンプルディレクトリ構造...

CA-r-00000

FR-r-00000

Quebec-r-00000

TX-r-00000

US-r-00000

個別内容


3858241 フィリップ・E・デュランド

ロニー・H・ノリス


3858242

エルウィン・R・グッディング


3858244

リチャード・L・マン


4

1 に答える 1

0

ここで非常に古い質問に答えていることはわかっていますが、とにかくここでいくつかのアイデアを投げさせてください。1 回の reduce 呼び出しで取得したすべてのレコードを使用して、reducer で TreeMap を作成しているようです。Mapreduce では、すべてのレコードをメモリに保持する余裕はありません。とそれに関連するpatent_noすべてのマップを作成しています。必要なのは に基づいてレコードを分離することだけなので、mapreduce フレームワークのソートを活用してみませんか。namespatent_nopatent_no

書き込み可能なキー自体にpatent_noandnameを含める必要があります。country

  • Partitionerに基づいてパーティションのみに書き込みますcountry
  • 並べ替えは、、、である必要がcountryありpatent_noますname
  • Grouping comparatorにグループへの書き込みを行う必要があります。countrypatent_no

その結果、同じレコードはすべてcountry同じリデューサーに移動し、 and でソートされpatent_noますname。そして、同じレデューサー内で、別のpatent_noが別のreduce呼び出しに行きます。あとは、MultipleOutputs に簡単に書き込むだけです。したがって、メモリ内の TreeMap をすべて取り除きます。

そして、私があなたに気をつけなければならないことをお勧めするいくつかのポイントは次のとおりです。

  • new MultipleOutputsreduce メソッドで毎回作成しないでください。代わりに、setup()メソッドを作成し、そのメソッドで 1 つだけ作成する必要がありますsetup()
  • new Text()毎回作成するのではなく、setup メソッドで作成し、同じインスタンスを のset("string")メソッドで再利用しますText。JavaのGCはとにかくそれをガベージコレクションします。ただし、Java のガベージ コレクションがあまり頻繁に呼び出されないように、できるだけメモリの使用量を少なくするように常に心がけてください。
于 2015-01-10T16:35:39.277 に答える