以下哪个查询将使用该索引?

时间:2016-09-04 15:16:44

标签: mongodb mongodb-query mongodb-indexes

给定集合foo具有以下索引:

db.foo.createIndex( { a : 1, b : 1, c : 1 } )

我们需要选择以下哪个查询才能使用索引?

  1. db.foo.find( { c : 1 } ).sort( { a : -1, b : 1 } )
  2. db.foo.find( { b : 3, c : 4 } )
  3. db.foo.find( { a : 3 } )
  4. db.foo.find( { c : 1 } ).sort( { a : 1, b : 1 } )
  5. 我很惊讶 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 } )
    

2 个答案:

答案 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