The MongoDB query optimizer works by trying different plans to determine which approach works best for a given query. The winning plan for that query pattern is then cached for the next ~1,000 queries or until you do an explain()
.
To understand which query plans were considered, you should use explain(1)
, eg:
db.col.find({category:'A'}).sort({updated: -1}).explain(1)
The allPlans
detail will show all plans that were compared.
If you run a query which is not very selective (for example, if many records match your criteria of {category: { $ne:'A'}}
), it may be faster for MongoDB to find results using a BasicCursor (table scan) rather than matching against an index.
The order of fields in the query generally does not make a difference for the index selection (there are a few exceptions with range queries). The order of fields in a sort does affect the index selection. If your sort()
criteria does not match the index order, the result data has to be re-sorted after the index is used (you should see scanAndOrder:true
in the explain output if this happens).
It's also worth noting that MongoDB will only use one index per query (with the exception of $or
s).
So if you are trying to optimize the query:
db.col.find({category:'A'}).sort({updated: -1, rating: -1})
You will want to include all three fields in the index:
db.col.ensureIndex({category: 1, updated: -1, rating: -1})
FYI, if you want to force a particular query to use an index (generally not needed or recommended), there is a hint()
option you can try.