2012-03-20 38 views
3

我有一个收集 “数字” 与200000文档对象与{号:ⅰ} i = 1到200000搜索时间>而不索引

在没有任何索引$ GT:10000给出nscanned 200000个115毫秒。 使用索引号$ gt:10000可扫描189999和355 ms。

为什么更多的时间与索引?

> db.numbers.find({number: {$gt: 10000}}).explain() 
{ 
    "cursor" : "BasicCursor", 
    "nscanned" : 200000, 
    "nscannedObjects" : 200000, 
    "n" : 189999, 
    "millis" : 115, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : false, 
    "indexOnly" : false, 
    "indexBounds" : { 

    } 
} 

> db.numbers.ensureIndex({number: 1}) 

> db.numbers.find({number: {$gt: 10000}}).explain() 
{ 
    "cursor" : "BtreeCursor number_1", 
    "nscanned" : 189999, 
    "nscannedObjects" : 189999, 
    "n" : 189999, 
    "millis" : 355, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : false, 
    "indexOnly" : false, 
    "indexBounds" : { 
      "number" : [ 
        [ 
          10000, 
          1.7976931348623157e+308 
        ] 
      ] 
    } 
} 
+0

我试过很多次迭代,但不同的是几乎与200ms的指数和指数没有。 – 2012-03-20 17:53:33

回答

5

在这种情况下,索引不起作用,因为您的匹配结果集几乎包含整个集合。这意味着它必须加载到RAM中并遍历大部分索引,并加载到RAM中并遍历文档本身。

没有索引,它只会执行表扫描,检查每个文档并在匹配时返回。

在这种情况下,查询将返回几乎整个集合,索引可能没有帮助。

添加.limit()将加快查询速度。您还可以强制查询优化器不使用索引与.hint():

db.collection.find().hint({$natural:1}) 

你也可以强制查询直接从指数本身提供的结果值限制选定字段只有那些你已经索引。这使得它可以避免在索引扫描之后加载任何文档。

试试这个,看看输出解释这里所指"indexOnly":true

db.numbers.find({number: {$gt: 10000}}, {number:1}).explain() 

详情:

http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-CoveredIndexes

+0

很棒的信息,谢谢... – 2012-03-20 18:03:14