I have one collection “numbers” with 200000 document object with {number: i} i = 1 to 200000.
Without any index $gt: 10000 gives nscanned 200000 and 115 ms.
With index on number $gt: 10000 gives nscanned 189999 and 355 ms.
Why more time with indexing?
> 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
]
]
}
}
In this case, the index doesn’t help because your matching result set consists of almost the entire collection. That means it has to load into RAM and traverse most of the index, as well as load into RAM and traverse the documents themselves.
Without the index, it would just do a table scan, inspecting each document and returning if matched.
In cases like this where a query is going to return almost an entire collection, an index may not be helpful.
Adding a .limit() will speed the query up. You can also force the query optimizer to not use the index with .hint():
You could also force the query to provide the result values directly from the index itself by limiting the selected fields to only the ones you’ve indexed. This allows it to avoid the need to load any documents after doing the index scan.
Try this and see if the explain output indicates
"indexOnly":trueDetails here:
http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-CoveredIndexes