2017-03-22 3 views
0

私のコレクションには10Mのドキュメントがあり、movieIdという名前のフィールドがあります。ドキュメントでは、この構造を有する:MongoDB一致インデックスvsインデックスなし - 集約

{ 
    "_id" : ObjectId("589bed43e3d78e89bfd9b779"), 
    "userId" : 1, 
    "movieId" : 122, 
    "rating" : 5, 
    "timestamp" : 838985046, 
    "newId" : 0.0 
} 
  • MOVIEIDは1から7000の間の数です。
  • 私はこのコレクションの2つのバージョンを持っています(重複しています)。一つ目はMOVIEID以上のインデックスを持つ:
db.collection.createIndex({movieId:1}); 
  • 他のバージョンでは、このインデックスを持っていません。 1(

    db.collection.aggregate(
    [{ 
        $match:{"movieId":{$lte:VarSize}} 
    }]);` 
    

    私はこのクエリのパフォーマンスを比較していますが、VarSizeが少ないときには、インデックスを持つコレクションを照会することは速いです:

私は、次のクエリを(VarSizeは単なる変数です)実行しています-2秒)、索引なしでコレクションに照会するには14秒かかります。しかし、VarSizeが1000より大きい場合、索引付けされたコレクションを照会することは、索引付けされていないコレクションよりも遅くなります。インデックス付きコレクションのクエリに2倍の時間がかかります。

更新#1:
Match performance

更新#2:
"のtoArrayは" VarSizeが大きくなっている間に増加する値を得るために私を助けました。それがなければ、戻り値は単なるカーソルだと私は思う。
Match over collection without index

+0

「movieId」というフィールドが1つしかないドキュメントはありますか? '_id'フィールドはどうでしょうか? –

+0

コレクションのサンプルドキュメントを表示して、インデックスが何であるかを正確に確認できますか? –

+0

@SergeyBerezovskiyはい_idフィールドがありますが、他の多くのフィールドでもクエリの実行に問題はないと思います。 –

答えて

0

かなりまっすぐであるべきだと思います。まず第一に、それは覆われたクエリではない、あなたはより良いperfを得るでしょう。インデックス付きcollでここではムービーIDと_idも持つ完全なドキュメントを選択しています。 基礎に固執する私はDBで何が起きているのかを説明しようとします。 dbには10のドキュメントしかありませんが、ムービーIDはシーケンシャルな値であることを考慮してください(そうでなくてもOKですが、あなたはvarSize = 2を与える)

  1. を目的を理解するので、それはそれは3つのインデックスキーをチェックして、DBにアクセスし、DBから、それらの対応する3つのドキュメントを取得する必要があり、映画のID 0を持つ唯一のドキュメントを取得する必要がある1、2。これはすべてあなたがインデックスを持っているときです。あなたがインデックスを持っていないときは、単純なコレクションスキャンですべてのドキュメントをチェックします。だから、インデックスなしでそれは時間を取っている。
  2. ケース2 - すべてのドキュメントを間接的に尋ねるようにvarSize = 9を指定します。インデックス化されたコレクションでは、最初に10個のインデックスエントリをすべて確認した後、それらの10個のインデックスエントリに対応するすべてのドキュメントを取得します。したがって、すべてのドキュメントが必要だったとしても、インデックスを作成してからドキュメントを取得しました。非インデックス環境では、コレクションに直接移動し、varSizeをムービーIDと比較し、ドキュメントをフェッチします。時間がここで保存され、インデックスエントリのチェックに浪費されています。

注 - ここ2のケースでは、問題をよりよく説明するためにvarSize = 9を使用しました。私はvarSize = maxMovieId場合は、インデックスされたコレクションでもインデックスを使用しないと思う。しかし、もしvarSizeがいくらか70または80%の価値を持っていれば、インデックスを使うことを試みるでしょう。それは速くなりますが、もっと時間を消費することになります。 また、クエリプランナは、varSizeがmaxMovieIdに向いているクエリに時間がかかることを最終的に認識し、インデックス付きコレクションに対してもインデックスを使用しません。しかし、クエリー・プランナーがバックグラウンドでクエリーを実行し、バックグラウンドでタイムリーな内部でさまざまなプランをチェックするので、いつ発生するのかはわかりません。

範囲クエリを実行すると、インデックス作業が「非常にまっすぐ」ではありません。おそらく彼らはequality-sort-range ruleを持っているのでしょう。

編集:私はここで、正しかった私のテストは

  • を検索結果れるI、構造10 M文書追加{_id:オブジェクトID、 "A":1} forループを使用して "" 値が増加したが毎回1つずつ新しい文書があります。インデックスがなければ、$ lteで任意の値を問い合わせると、私のマシンではほぼ同じ時間〜650msかかる。 a:$ lte = 1の場合でも、同じ時間がかかりました。したがって、各文書をチェックする必要があるため、索引がない場合には時間が直線的になります。密接に見ると、executeStatsの出力はCOLLSCANというステージが1つしかないことに気がつきます。この段階では、10M文書をすべて確認するだけです。
  • インデックス{a:1}の後に同じコレクションについて同じ説明を実行しました。そして結果はすべて一緒に異なっていた。 a:$ lte = 10またはa:$ lte = 100の場合、約47 msの時間がかかります。しかし、もし私が$ lte = 1000000を与えると、それは1442ミリ秒かかり、それはインデックスなしで取ったもののほぼ2.5倍になります。そして、私はexecutionStatsの出力をチェックした後に理由を得ました。今は2つの段階があります。 1段COLLSCANに比べて時間がかかるIXSCANとFETCHがあります。

私は今あなたのグラフを理解していない、私はそれが間違っていると思うか、それを明確に説明することができないか、オレンジ色の線は10M文書では時間がかかりません。レンジ・クエリを実行するときに範囲値が大きく影響するため、varSizeをどこに取り込んでいるかを明確にすることができます。

+0

あなたの答えに感謝します。今、それは本当です、インデックスを通過するためのこのステップが常にあり、場合によっては最も効率的ではありません。しかし、この画像では私の結果[比較グラフ](https://i.stack.imgur.com/m2tBs.png)を表示しています。インデックス化されたコレクションの結果は正しいと思います。しかし、インデックス化されたコレクションはグラフ内で決して減少しません。まず、すべての文書に尋ねなければならないし、VarSizeが大きいほど返す文書の数が多くなるからです。私はさまざまな種類のコレクションを試してみましたが、私は同じ結果を得ました。私はまた、インデックスの使用を確認する統計を見た。 –

+0

私の英語は申し訳ありません。 –

+0

ただし、インデックスはありません。あなたのグラフごとに時間が減少しています。 –

関連する問題