注: この回答はMongoDB3.2.4に基づいています。
explain()の使用法を発見することは価値があります
MongoDBで。 explain()
クエリの出力(例:db.collection.explain().find(...) )クエリで使用されているインデックスを確認し、 db.collection.explain('executionStats')
また、メモリ内のSORTが原因でクエリが成功したか失敗したかが表示されます 制限。
$ in
$in クエリは、一連の等式クエリと考えることができます。例:{a: {$in: [1,3,5]}} {a:1}, {a:3}, {a:5}と考えることができます 。 MongoDBは$inをソートします クエリを続行する前に配列を作成し、{$in: [3,5,1]} {$in: [1,3,5]}と同じです 。
コレクションのインデックスが
であると仮定しましょう。{a:1, b:1}
-
aによる並べ替えdb.coll.find({a: {$in: [1,3,5]}}).sort({a:1})MongoDBは
{a:1,b:1}を使用できるようになります このクエリは{a:1}, {a:3}, {a:5}の和集合と考えることができるためインデックス。 クエリ。{a:1}で並べ替える インデックスプレフィックスの使用を許可します 、したがって、MongoDBはメモリ内の並べ替えを実行する必要はありません。同じ状況がクエリにも当てはまります:
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({a:1})sort({a:1})以降 インデックスプレフィックス(a)も使用します この場合)、メモリ内のSORTしたがって、ステージは必要ありません。 -
bによる並べ替えこれは、
aで並べ替えるよりも興味深いケースです。 。例:db.coll.find({a: {$in: [1,3,5]}}).sort({b:1})explain()このクエリの出力には、SORT_MERGEというステージがあります。 。find()であることを忘れないでください クエリの一部は、{a:1}, {a:3}, {a:5}と考えることができます。 。クエリ
db.coll.find({a:1}).sort({b:1})メモリ内のSORTは必要ありません{a:1,b:1}の性質によるステージ インデックス:つまり、MongoDBは(ソートされた)インデックスをたどり、bでソートされたドキュメントを返すことができます。aの等式パラメータを満たした後 。例:各a、多くのbがあります すでにbで並べ替えられています インデックスのため。$inを使用する 、クエリ全体は次のように考えることができます:-
db.coll.find({a:1}).sort({b:1}) -
db.coll.find({a:3}).sort({b:1}) -
db.coll.find({a:5}).sort({b:1}) - 上記の個々のクエリ結果を取得し、
bの値を使用してマージを実行します 。クエリはメモリ内の並べ替えステージは必要ありません 個々のクエリ結果はすでにbで並べ替えられているためです 。 MongoDBは、(既に並べ替えられた)サブクエリの結果を単一の結果にマージする必要があります。
同様に、クエリ
db.coll.find({a: {$in: [1,3,5]} ,b:{$gte:1, $lt:2}}).sort({b:1})SORT_MERGEも使用します ステージであり、上記のクエリと非常によく似ています。違いは、個々のクエリが範囲に基づいてドキュメントを出力することです。b(すべての代わりにb)各a(bで並べ替えられます インデックス{a:1,b:1}による )。したがって、クエリにはメモリ内の並べ替えステージは必要ありません。 -
$または
$orの場合 インデックスを使用するためのクエリ、すべての句$orで 式にはインデックスが関連付けられている必要があります
。この要件が満たされている場合、クエリでSORT_MERGEを使用することができます。 $inのようなステージ クエリ。例:
db.coll.explain().find({$or:[{a:1},{a:3},{a:5}]}).sort({b:1})
ほぼ同じクエリプラン、インデックスの使用、およびSORT_MERGE $inのようにステージングする 上記の例。基本的に、クエリは次のように考えることができます:
-
db.coll.find({a:1}).sort({b:1}) -
db.coll.find({a:3}).sort({b:1}) -
db.coll.find({a:5}).sort({b:1}) - 上記の個々のクエリ結果を取得し、
bの値を使用してマージを実行します 。
$inと同じように 前の例。
ただし、このクエリ:
db.coll.explain().find({$or:[{a:1},{b:1}]}).sort({b:1})
インデックスを使用できません ({b:1}がないため 索引)。このクエリによりコレクションスキャンが実行されるため、メモリ内の並べ替えステージがあります インデックスが使用されていないため。
ただし、インデックスを作成する場合{b:1} 、クエリは次のように進行します:
-
db.coll.find({a:1}).sort({b:1}) -
db.coll.find({b:1}).sort({b:1}) - 上記の個々のクエリ結果を取得し、
bの値を使用してマージを実行します (インデックス{a:1,b:1}のため、両方のサブクエリですでに並べ替えられています および{b:1}。
MongoDBは、{a:1}の結果を結合します および{b:1} クエリを実行し、結果に対してマージを実行します。マージプロセスは線形時間です。 O(n) 。
結論として、$or クエリでは、すべての用語にsort()を含むインデックスが必要です。 ステージ。そうしないと、MongoDBはメモリ内の並べ替えを実行する必要があります。