给定集合foo
具有以下索引:
db.foo.createIndex( { a : 1, b : 1, c : 1 } )
我们需要选择以下哪个查询才能使用索引?
db.foo.find( { c : 1 } ).sort( { a : -1, b : 1 } )
db.foo.find( { b : 3, c : 4 } )
db.foo.find( { a : 3 } )
db.foo.find( { c : 1 } ).sort( { a : 1, b : 1 } )
我很惊讶 3 , 4 是正确选项而 1 , 2 不是。< / p>
db.foo.find( { a : 3 } )
这似乎可以使用索引,但_id
未预测出来。
db.foo.find( { c : 1 } ).sort( { a : 1, b : 1 } )
我们正在寻找位于索引的右侧的c
db.foo.find( { c : 1 } ).sort( { a : -1, b : 1 } )
db.foo.find( { b : 3, c : 4 } )
答案 0 :(得分:2)
查询1
db.foo.find( { c: 1 } ).sort( { a: -1, b: 1 } );
使用{ c: 1 }
进行过滤将不会使用该索引,因为{ c: 1 }
不是{ a: 1, b: 1, c: 1 }
(documentation)的前缀。使用{ a: -1, b: 1 }
排序将不使用索引,因为排序方向(1或-1)确实很重要(documentation)。
查询2
db.foo.find( { b: 3, c: 4 } );
使用{ b: 3, c: 4 }
进行过滤不会使用索引,因为{ b: 1, c: 1 }
不是{ a: 1, b: 1, c: 1 }
的前缀。
查询3
db.foo.find( { a: 3 } );
使用{ a: 3 }
进行过滤将使用索引,因为{ a: 1 }
是{ a: 1, b: 1, c: 1 }
的前缀。
这似乎能够使用索引但是_id不会被预测 进行。
字段_id
将位于查询结果中,除非您指定相反的结果。
对于文档{ _id: 1, a: 3, b: 4, c: 5 }
,请考虑下一个查询及其结果
> db.foo.find( { a: 3 }, { _id: 0, a: 1, b: 1, c: 1 } );
{ "a": 3, "b": 4, "c": 5 }
> db.foo.find( { a: 3 }, { a: 1 } ).explain("executionStats");
...
"executionStats": {
"totalKeysExamined" : 1,
"totalDocsExamined" : 0,
...
> db.foo.find( { a: 3 } );
{ "_id": 0, "a": 3, "b": 4, "c": 5 }
> db.foo.find( { a: 3 } ).explain("executionStats");
...
"executionStats": {
"totalKeysExamined": 1,
"totalDocsExamined": 1,
...
请注意,在第二种情况下,文档的_id
是在索引扫描后从集合("totalDocsExamined": 1
)中提取的,因为查询并未说明结果中不需要_id
字段。
查询4
db.foo.find( { c: 1 } ).sort( { a: 1, b: 1 } );
使用{ a: 1, b: 1 }
排序将使用索引,因为{ a: 1, b: 1 }
是{ a: 1, b: 1, c: 1 }
的前缀子集(对于非前缀子集 - 请参阅documentation),并且排序键列在与{ a: 1, b: 1, c: 1 }
(documentation)中的顺序,方向相同。但是,索引不会用于过滤,因为{ c: 1 }
不是{ a: 1, b: 1, c: 1 }
的前缀。考虑下一个查询及其结果
> db.foo.find( { c: 1 }, { _id: 0 } ).sort( { a: 1, b: 1 } ).explain("executionStats");
...
"executionStages": {
"stage": "FETCH",
"filter": {
"c": { "$eq": 3 } // filtering is done by fetching from the collection
},
"inputStage": {
"stage": "IXSCAN",
"indexBounds": {
"a": [ "[MINKEY, MAXKEY]" ],
"b": [ "[MINKEY, MAXKEY]" ],
"c": [ "[MINKEY, MAXKEY]" ] // index was not used for filtering c
}
...
> db.foo.find( { a: 1 }, { _id: 0 } ).sort( { a: 1, b: 1 } ).explain("executionStats");
...
"executionStages": {
"stage": "PROJECTION",
"inputStage": {
"stage": "IXSCAN",
"indexBounds": {
"a": [ "[3.0, 3.0]" ], // index was used for filtering a
"b": [ "[MINKEY, MAXKEY]" ],
"c": [ "[MINKEY, MAXKEY]" ]
}
...
请注意,在第二种情况下,使用索引完成了过滤和排序,并且没有调用该集合。
答案 1 :(得分:1)
关于第一个问题:db.foo.find({c:1}).sort({a:-1,b:1})
方向很重要,你在这里有更多的信息 why does direction of index matter in MongoDB?
您可以查看http://openmymind.net/mongodb.pdf =&gt;第56页
关于第二个问题。索引中定义的键的顺序也很重要。 这里有更多信息=&gt; Mongodb query - Does sequence of key matters in usage of compound index