2011-09-06 4 views
7

私はMongoDBの初心者ですが、私が読んだところでは、MongoDBデータベースの平均値と合計値を求めるさまざまな方法があり、それぞれにさまざまな利点と欠点があります。MongoDBの 'AVG'と 'SUM'の機能は、どんなヒントですか?

私は、効率的(高速)な方法で、値の選択の合計と値の選択の平均を見つける方法を主に求めています。照会されているコレクション内の

文書は(他の多くの分野で)このような構造に似ている:、

{ 
    "_id": ObjectId('4e650107580fd649e5000005'), 
    "date_added": ISODate("2011-09-05T00:00:00Z"), 
    "value": 1500 
} 

があり、私のアプリケーションでは、常に可能ではないの合計のようなものを事前計算値の選択に理由(日付範囲に基づいて、例えば、開始日と終了日の間に、平均が何か)を変更することができる。これは、平均を事前に計算する際の同様の問題です。

私が読んだところでは、MapReduceはリアルタイム(オンデマンド)検索には理想的ではないため、これも問題にはなりません。 (注意:これはpymongoを使用している)

response = request.db['somecollection'].find(
    { 
     'date_added': { 
      '$gte': date_start, 
      '$lte': date_end 
     } 
    }, 
    { 
     'value':1 
    } 
).limit(500) 

を次に応答上forループを使用してPythonで計算をしている私は、このようにコレクションを照会しています現時点では

。 500の結果の限界は、それが遅すぎるのを避けるために任意です。私は値を取得するだけで、他のフィールドは取得しません。

これは、この計算を行う最も効率的な方法ですか、必要なものを達成するための他の方法がありますか?

警告:私はおそらくシャーディングを使用するので、私はそれが使用される機能ですので、私はMapReduceのを使用することはできません

  • 将来的にgroup機能を使用することはできません

    • -the-flyユーザー
    • 合計/平均値の選択がほとんど常に異なるため、私は多くの私の合計/平均をあらかじめ計算することはできません
    • 私はtryoverflowとWebを試してみました。この種のものを行う方法についての勧告を見つけて、それはかなりオープンエンドだ

    EDIT:

    私は、文書の数は、私は何もすることができ、上記掲載のクエリから返されたことを指摘しなければならない

    1文書から数百になるかもしれませんが、返される文書の最大数は約150(平均約60または70)です。

  • 答えて

    4

    あなたは考えているほど遅くないかもしれません。私はいくつかの大規模なデータセットに対してリアルタイムの集約に使用しましたが、時には高速ではありませんが、それはより良い場合があります。あなたは、さらに多くの物事をスピードアップシャードクラスタにデータを分散を検討する必要がある場合は、あなたが集約している初期データ、例えば:

    db.collection.mapReduce(m, r, { query : { year: 2011 } }); 
    

    のサイズを絞り込むことができればベストです。次に、map-reduce処理は、並列実行されている複数のシャード間でスケールアウトすることができます。

    +0

    の問題を参照してください.MapReduceでもっと実験しています。私はそれがデータセット/クエリ/などの間で異なることを知っていますが、あなたのケースでは、実際にはユーザーに気付かれないほど速かったです(つまり、半秒以下)。 – johneth

    +0

    500-5000msの間で変化しますが、一部のデータセットはかなり大きかった(100M +ドキュメント)ので、ビジー/進捗インジケータが必要でしたが、十分に速いです。 JavaScriptエンジンをシングルスレッドのSpiderMonkeyからV8にアップグレードすると、Map-Reduceのパフォーマンスが向上するはずです。 –

    +0

    ああ、それは有望だと思います。現時点では、データセットは非常に小さく(数千万ではなく数百万で測定されます)、時間が経つにつれて大きくなります。 – johneth

    2

    簡単な答えは次のとおりです。

    1. ことが可能事前計算はすべてあなたが事前計算することができます。
    2. データ範囲で集計データが必要な場合、集計はできるだけ早く実行する必要があります。次に、map/reduce + shardingを使用して複数のマシン間で計算を分散します。

    しかし、同じ時間にMongoDBガイドのは言う:

    のMapReduceを使用しての価格はスピードです:「本当のグループは、特に スピーディーではありませんが、MapReduceは遅く、 で使用されることを想定されていませんあなたはバックグラウンドジョブとしてMapReduceを実行し、結果の コレクションを作成してから、そのコレクションを実際に 時間に照会することができます。

    したがって、mongodbはリアルタイムデータ集計に最適なソリューションではないようです。

    +0

    私は間違いなくすべての値を事前に計算しています。残念ながら、少なくとも私は1台のマシンに限定されているので、複数のマシンに分散することはできません。私の例では、返されるドキュメントの数はMapReduceの使用を検討するのに十分な速度に影響しますか? (質問の最後に返された平均文書数を追加しました) – johneth

    3

    MongoDBは

    OKを指摘し、そのマップ/削減し、集約、現在いくつかの深刻な問題を抱えています。

    大きな注意点:MongoDBインスタンスには、「javascriptエンジン」インスタンスしか存在できません。つまり、サーバー上で2つのマップ/リダクションを同時に実行することはできません。また、map-reduceを実行するためのコアは1つだけです。

    あなたがやっていることの場合、あなたは基本的に "自分の" M/Rを動かしています。欠点は余分なネットワークトラフィックです。メリットとしては、問題(Webサーバーから)で多くのコアを投げられることです。

    あなたの重要な問題

    は、私は私の合計/平均値の多くを事前計算することはできません/平均値を合計する値の選択は

    ほとんど常に異なっているので、何も一般的ではありません「すべての可能な」クエリを最適化する方法。システムがすべての範囲のすべてのフィールドに沿って合計して集計できるようにするには、最終的に大きすぎるフィールド/範囲のセットがあります。

    これを「解決する」方法は、フィールドと範囲のセットを減らすことです。

    毎日、毎時のカウンタと合計をこれらのカウンタに保持します。少なくとも、クエリに答えるためにスキャンする必要があるドキュメントの数を減らします。

    1

    MongoDBはバージョン2.1.1(現在は2011年11月1日に予定されている)のsum/avg/min/maxのようなネイティブな集計関数を得る予定です。詳細とステータスについては、https://jira.mongodb.org/browse/SERVER-447

    関連する問題