1

約10億のデータポイントを持つデータセットがあります。これから抽出したい約4600万の一意のデータポイントがあります。

Hadoopを使用して一意の値を抽出したいのですが、Hadoopで「メモリ不足」とJavaヒープサイズエラーが発生し続けます。同時に、Pythonセット(ハッシュテーブル)を使用して、これを1つのボックスでかなり簡単に実行できます。 、必要に応じて。)

私はこれらの一意の値を抽出するためにかなり単純なアルゴリズムを使用しています。マップ内の10億行を解析し、次のような行を出力しています。

UniqValueCount:I    a
UniqValueCount:I    a
UniqValueCount:I    b
UniqValueCount:I    c
UniqValueCount:I    c
UniqValueCount:I    d

次に、「aggregate」レデューサーを実行して結果を取得します。これは、上記のデータセットでは次のようになります。

I   4

これは小さな値のセットではうまく機能しますが、10億のデータポイント(前述のように4600万のキーがある)に対してこれを実行すると、ジョブは失敗します。

これをAmazonのElasticMapReduceで実行していますが、6つのm2.4xlargeノード(それぞれ最大メモリノードは68.4 GB)を使用しても、ジョブは「メモリ不足」エラーで失敗します。

しかし、1つのm1.large(8 GBのメモリを備えたはるかに小さいボックス)でSetデータ構造(ハッシュテーブル)を持つPythonコードを使用して、一意の値を抽出することができます。4,600万のユニークがそれほど多くのメモリを消費するべきではないため、Hadoopジョブが失敗することに混乱しています。

何がうまくいかない可能性がありますか?UniqValueCountを間違って使用していますか?

4

1 に答える 1

2

シャッフルでメモリエラーが発生している可能性があります。Hadoopがレデューサーを起動する前にキーを並べ替えることを忘れないでください。ほとんどのアプリでは並べ替え自体は必要ありませんが、Hadoopはこれをキーに属するすべての値を集計する方法として使用します。

あなたの例では、マッパーは同じ値を何度も書き込むことになりますが、特定のキーに対して持っている一意の数だけを気にします。これがあなたが今していることです:

Mapper output:
I -> a
I -> a
I -> a
I -> a
I -> b
I -> a
I -> b

Reducer input:
I -> [a, a, a, a, b, a, b]

Reducer output:
I -> 2

ただし、この場合、実際には5*aまたは2*bを記述する必要はありません。一意性のみを考慮しているため、1回で十分です。したがって、レデューサーで一意をカウントする代わりに、各値を1回だけ送信するようにすることで、多くのオーバーヘッドを直接削減できます。

Mapper output:
I -> a
I -> b

Reducer input:
I -> [a, b]

Reducer output:
I -> 2

これにより、ネットワーク帯域幅が効果的に削減され、並べ替えるキーが少なくなるため、シャッフルがはるかに簡単になります。

これは2つの方法で実行できます。

  • マッパーの直後でレデューサーの前に実行され、レデューサーに送信する前にのみ一意を保持するコンバイナーをジョブに追加します。
  • マッパーを変更して、すでに送信したもののマッピングを保持し、以前にこのマッピングを送信したことがある場合は送信しないようにします。
于 2013-01-18T17:59:35.517 に答える