我有一个带有200000文档对象的“数字”集合,其中{number:i} i = 1到200000.
没有任何索引$ gt:10000给出了nscanned 200000和115 ms。 使用索引编号$ gt:10000给出nscanned 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 :(得分:5)
在这种情况下,索引没有帮助,因为匹配的结果集几乎包含整个集合。这意味着它必须加载到RAM并遍历大部分索引,以及加载到RAM并遍历文档本身。
如果没有索引,它只会进行表扫描,检查每个文档并返回匹配。
在这样的情况下,查询将返回几乎整个集合,索引可能没有帮助。
添加.limit()会加快查询速度。您还可以强制查询优化器不使用带有.hint()的索引:
db.collection.find().hint({$natural:1})
您还可以通过将所选字段限制为仅编入索引的字段来强制查询直接从索引本身提供结果值。这使得它可以避免在进行索引扫描后加载任何文档。
试试这个并查看解释输出是否显示"indexOnly":true
db.numbers.find({number: {$gt: 10000}}, {number:1}).explain()
详细信息: