収益/tl;dr: インデックスb
a
の場合、「スキップ」できます およびc
等式または不等式について照会されますが、たとえば、c
でのソートについては照会されません。 。
これはとても良い質問です。残念ながら、これに正式に答える詳細なものは見つかりませんでした。このようなクエリのパフォーマンスはここ数年で向上したと思うので、このトピックに関する古い資料は信用しません。
インデックスの選択性と、等式、不等式、または並べ替えをクエリするかどうかに依存するため、全体が非常に複雑になります。したがって、explain()
はあなたの唯一の友達ですが、私が見つけたものは次のとおりです:
警告 :今来るのは、実験結果、推論、推測の混合です。私はカイルのアナロジーを過度に伸ばしているかもしれません、そして私は完全に間違っているかもしれません (そして不幸なことに、私のテスト結果は私の推論と大まかに一致しているためです。)
Aのインデックスを使用できることは明らかです。これは、Aの選択性によっては、確かに非常に役立ちます。 「スキップ」Bは注意が必要な場合とそうでない場合があります。これをカイルの料理本の例と同じように保ちましょう:
French
Beef
...
Chicken
Coq au Vin
Roasted Chicken
Lamb
...
...
「シャトーブリアン」というフランス料理を探すように言われたら、インデックスA
を使用できます。 そして、材料がわからないので、A
のすべての料理をスキャンする必要があります 。一方、各カテゴリの料理のリストは、インデックスC
で並べ替えられていることを私は知っています。 、したがって、各材料リストで「Cha」で始まる文字列を探すだけで済みます。 50の材料がある場合、1つではなく50のルックアップが必要になりますが、それはすべてのフランス料理をスキャンするよりもはるかに優れています!
私の実験では、この数は
b
の個別の値の数よりもはるかに少なかった。 :2を超えることはありませんでした。ただし、これは1つのコレクションでのみテストしたものであり、おそらくb
の選択性に関係しています。 -インデックス。
すべてのフランス料理のアルファベット順のリストを提供するように依頼された場合 しかし、私はトラブルに陥るでしょう 。 C
のインデックス 価値がないので、これらすべてのインデックスリストをマージソートする必要があります。そのためには、すべての要素をスキャンする必要があります。
これは私のテストに反映されています。ここにいくつかの簡略化された結果があります。元のコレクションには日時、int、文字列が含まれていますが、物事をシンプルにしたかったので、すべてintになりました。
基本的に、クエリには2つのクラスしかありません。nscanned
のクラスです。 <=2*limit
、およびコレクション全体(120kドキュメント)をスキャンする必要があるもの。インデックスは{a, b, c}
です。 :
// fast (range query on c while skipping b)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }});
// slow (sorting)
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "c" : -1});
> db.Test.find({"a" : 43, "c" : { $lte : 45454 }}).sort({ "b" : -1});
// fast (can sort on c if b included in the query)
> db.Test.find({"a" : 43, "b" : 7887, "c" : { $lte : 45454 }}).sort({ "c" : -1});
// fast (older tutorials claim this is slow)
> db.Test.find({"a" : {$gte : 43}, "c" : { $lte : 45454 }});
マイレージは異なります。