上記で行っていることも同様に機能するはずですが、これは単一のキーのすべてのデータがメモリに収まることを前提としています。そうであれば、Reducer ですべての値をメモリに保持し、合計を計算してから、各キーと値のペアの限界値を計算できます。これは一般に「ストライプ」アプローチとして知られています。
ただし、ほとんどの場合、これは当てはまり、データがメモリに収まらない可能性があります。この場合、実際のキーと値のペアの前に値を送信して合計を計算する方法を見つける必要があります。これにより、値を使用して限界値を計算し、すぐに値を発行できるようになります。
これは、「反転順序」設計パターンの候補です。相対頻度を計算する必要がある場合に役立ちます。基本的な考え方は、Mapper の最後で、キーと値のペアの 1 つがすべての値に対して同じ共通キーを持つ各中間データに対して 2 つのキーと値のペアを発行することです。これは、合計を計算するために使用されます。
例:
For a, (r, 5) :
---------------
emit (a, r), 5
emit (a, *), 5
For a, (e, 6) :
---------------
emit (a, e), 6
emit (a, *), 6
For a, (w, 7) :
---------------
emit (a, w), 7
emit (a, *), 7
これが完了したら、キーの最初の値のみを使用して、中間のキーと値のペアのそれぞれを分割するパーティショナーが必要です。上記の例では、「a」を使用しています。
また、キーの 2 番目の部分に常に * を持つキーを配置するキーの並べ替え順序も必要になります。
このようにして、すべての中間キーの最初の部分に「a」があり、同じリデューサーになります。また、以下に示すようにソートされます -
emit (a, *), 5
emit (a, *), 6
emit (a, *), 7
emit (a, e), 6
emit (a, r), 5
emit (a, w), 7
レデューサーでキーと値のペアを反復処理するときに、キーの 2 番目の部分に * がある場合は、キーから値を単純に累積する必要があります。その後、累積値を使用して、他のすべてのキーと値のペアの限界を計算できます。
total = 0
for(value : values){
if (key.second == *)
total += value
else
emit (key.first , key.second, value, value/total)
}
この設計パターンは、ペア アプローチを使用する順序反転として一般に知られています。このデザイン パターンやその他のデザイン パターンの詳細については、この本の MapReduce デザイン パターンに関する章を読むことをお勧めします - http://lintool.github.com/MapReduceAlgorithms/。例を挙げてとてもよく説明されています。