2013-10-22 20 views
3

考虑以下蒙戈索引策略和查询,为什么MongoDB不能使用与查询非常相似(不精确)的复合索引?

指数:

db.collec.ensureIndex({a:1,b:1,c:1}); 

查询:

db.collec.find({"a":"valueA"},{"_id":0,"a":1,"c":1}).sort({"c":-1}).limit(150) 

上述查询返回的解释:

/* 0 */ 
{ 
    "cursor" : "BtreeCursor a_1_b_1_c_1", 
    "isMultiKey" : false, 
    "n" : 150, 
    "nscannedObjects" : 178, 
    "nscanned" : 178, 
    "nscannedObjectsAllPlans" : 279, 
    "nscannedAllPlans" : 279, 
    "scanAndOrder" : true, 
    "indexOnly" : true, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "millis" : 1, 
    "indexBounds" : { 
     "a" : [ 
      [ 
       "valueA", 
       "valueA" 
      ] 
     ], 
     "b" : [ 
      [ 
       { 
        "$minElement" : 1 
       }, 
       { 
        "$maxElement" : 1 
       } 
      ] 
     ], 
     "c" : [ 
      [ 
       { 
        "$minElement" : 1 
       }, 
       { 
        "$maxElement" : 1 
       } 
      ] 
     ] 
    } 
} 

的这里的问题是 其清晰y表示查询完全在索引上运行(如"indexOnly" : true)。 但是为什么"scanAndOrder" : true
根据Btree索引模型,c是在索引的尾部,因此它可以用于排序。没有?

为什么不使用它?

回答

0

如果您使用下面的索引扫描并且顺序将是错误的。

db.collec.ensureIndex({a:1,c:-1,b:1});

Check this out

+0

是的,我接受。但索引不是专门用于此查询,它已经在那里,我正在做这个查询的第一次。仅供参考,更改索引会影响查询,具体取决于索引。我的问题是为什么它不能使用索引来排序,即使c在索引的尾部? –

5

这是正确的,也documented

至于为什么:索引看起来基本上是这样的树:

  • 一个: “值A”
    • B: “ABC”
      • C:435
      • C:678
    • B:“BCD”
      • C:123
      • C:993

正如你所看到的,排序是正确的,上升的,但如果你采取阶c值不限制到固定的b的子集,你会得到[435, 678, 123, 993],这是不正确的,所以scanAndOrder是必需的。

不幸的是,没有index intersectioning的索引非常不灵活。

+1

可能还好添加:https://jira.mongodb.org/browse/SERVER-3071越多宣传越有可能mongodb inc可能会实施它 – Sammaye

+0

好点!我添加了答案的链接,因为很多人可能不知道这个词,即使他们知道这个特征。 – mnemosyn

相关问题