7

私はmongo dbから始めて、いくつかの簡単なことをしようとしています。「アイテム」プロパティを含むデータのコレクションでデータベースをいっぱいにしました。すべてのアイテムがコレクションにある時間を数えてみたかった

ドキュメントの例:

{ "_id" : ObjectId("50dadc38bbd7591082d920f0"), "item" : "Pons", "lines" : 37 }

そこで、MapReduce を実行するためにこれら 2 つの関数を設計しました (pymongo を使用して python で記述)。

all_map = Code("function () {"
           "    emit(this.item, 1);"
           "}")

all_reduce = Code("function (key, values) {"
                  " var sum = 0;"
                  " values.forEach(function(value){"
                  "     sum += value;"
                  " });"
                  " return sum;"
                  "}")

これは魔法のように機能したので、コレクションを埋め始めました。約 30.000 ドキュメントで、mapreduce はすでに 1 秒以上続きます... NoSQL は速度を自慢しているので、何か間違ったことをしているに違いないと思いました!

Stack Overflow での質問のおかげで、mongodb の集約機能について調べてみました。そこで、グループ + 合計 + ソートを使用しようとしました。これを思いついた:

db.wikipedia.aggregate(
 { $group: { _id: "$item", count: { $sum: 1  }  } }, 
 { $sort: {count: 1}  }
)

このコードは問題なく動作し、mapreduce セットと同じ結果が得られますが、速度は同じです。私は何か間違ったことをしていますか?パフォーマンスを向上させるために、hadoopなどの他のツールを使用する必要はありますか?

4

1 に答える 1

9

基本的に私のコメントを要約して回答します。Hadoop のような他の技術については、まだそれらを使用する時間を見つけることができなかったので話すことはできませんが、MongoDB について話すことはできます。

残念ながら、どのデータベースでも最悪の演算子の 2 つを使用しています。完全なテーブル スキャンでの計算フィールドとグループ化 (または個別) です。この場合の集約フレームワークは、フィールドを計算し、グループ化し、インメモリ ( http://docs.mongodb.org/manual/reference/aggregation/#_S_sort ) で計算されたフィールドをソートする必要があります。これは、MongoDB が実行する非常に非効率的なタスクであり、実際にはほとんどすべてのデータベースです。

独自のアプリケーションに合わせてリアルタイムでこれを行う簡単な方法はありません。結果をすぐに返す必要がない場合は、Map reduce が解決策になる可能性がありますが、この種のものを本当に待ちたくないのではないかと推測しているため、デフォルトの方法はグループを完全に根絶することです。

これは、事前集計によって行うことができます。したがって、 の別のコレクションを作成grouped_wikipediaし、アプリケーションでこれを管理するには、 and のようなアトミック演算子を使用して(upsert()出現回数をカウントするため)、 ごとに 1 つの行のみを取得するようにします。これはおそらく、この問題を解決する最も健全な方法です。$set$incitem

ただし、これにより、detail コレクションと一緒にこの余分なコレクションを管理しなければならないという別の問題が発生wikipediaしますが、これは、適切なパフォーマンスを得るための避けられない副作用であると考えています。その利点は、余分なコレクションを管理しなければならないという損失よりも大きくなります。

于 2012-12-27T21:06:17.777 に答える