Docs Home → Develop Applications → MongoDB Manual
Query Optimization
Indexes improve the efficiency of read operations by reducing the amount of data that query operations need to process. This simplifies the work associated with fulfilling queries within MongoDB.
Create an Index to Support Read Operations
If your application queries a collection on a particular field or set of fields, then an index on the queried field or a compound index on the set of fields can prevent the query from scanning the whole collection to find and return the query results. For more information about indexes, see the complete documentation of indexes in MongoDB.
Example
An application queries the inventory
collection on the
type
field. The value of the type
field is user-driven.
var typeValue = <someUserInput>; db.inventory.find( { type: typeValue } );
To improve the performance of this query, add an ascending or a
descending index to the inventory
collection on the type
field. [1] In mongosh
, you can
create indexes using the db.collection.createIndex()
method:
db.inventory.createIndex( { type: 1 } )
This index can prevent the above query on type
from scanning the
whole collection to return the results.
To analyze the performance of the query with an index, see Analyze Query Performance.
In addition to optimizing read operations, indexes can support sort
operations and allow for a more efficient storage utilization. See
db.collection.createIndex()
and
Indexes for more information about index
creation.
[1] | For single-field indexes, the selection between ascending and descending order is immaterial. For compound indexes, the selection is important. See indexing order for more details. |
Query Selectivity
Query selectivity refers to how well the query predicate excludes or filters out documents in a collection. Query selectivity can determine whether or not queries can use indexes effectively or even use indexes at all.
More selective queries match a smaller percentage of documents. For
instance, an equality match on the unique _id
field is highly
selective as it can match at most one document.
Less selective queries match a larger percentage of documents. Less selective queries cannot use indexes effectively or even at all.
For instance, the inequality operators $nin
and
$ne
are not very selective since they often match a large
portion of the index. As a result, in many cases, a $nin
or
$ne
query with an index may perform no better than a
$nin
or $ne
query that must scan all documents in
a collection.
The selectivity of regular expressions
depends on the
expressions themselves. For details, see regular expression and
index use.
Covered Query
A covered query is a query that can be satisfied entirely using an index and does not have to examine any documents. An index covers a query when all of the following apply:
all the fields in the query are part of an index, and
all the fields returned in the results are in the same index.
no fields in the query are equal to
null
(i.e. {"field" : null
} or {"field" : {$eq : null}}
).
For example, a collection inventory
has the following index on the
type
and item
fields:
db.inventory.createIndex( { type: 1, item: 1 } )
This index will cover the following operation which queries on the
type
and item
fields and returns only the item
field:
db.inventory.find( { type: "food", item:/^c/ }, { item: 1, _id: 0 } )
For the specified index to cover the query, the projection document
must explicitly specify _id: 0
to exclude the _id
field from
the result since the index does not include the _id
field.
Changed in version 3.6: An index can cover a query on fields within embedded documents. [2]
For example, consider a collection userdata
with documents of the
following form:
{ _id: 1, user: { login: "tester" } }
The collection has the following index:
{ "user.login": 1 }
The { "user.login": 1 }
index will cover the query below:
db.userdata.find( { "user.login": "tester" }, { "user.login": 1, _id: 0 } )
[2] | To index fields in embedded documents, use dot notation. |
Multikey Covering
Starting in 3.6, multikey indexes can cover queries over the non-array fields if the index tracks which field or fields cause the index to be multikey. Multikey indexes created in MongoDB 3.4 or later on storage engines other than MMAPv1 track this data.
Multikey indexes cannot cover queries over array field(s).
Performance
Because the index contains all fields required by the query, MongoDB can both match the query conditions and return the results using only the index.
Querying only the index can be much faster than querying documents outside of the index. Index keys are typically smaller than the documents they catalog, and indexes are typically available in RAM or located sequentially on disk.
Limitations
Restrictions on Indexed Fields
Geospatial indexes cannot cover a query.
Multikey indexes cannot cover queries over array field(s).
Tip
See also:
Restrictions on Sharded Collection
Starting in MongoDB 3.0, an index cannot cover a query on a
sharded collection when run against a
mongos
if the index does not contain the shard key,
with the following exception for the _id
index: If a query on a
sharded collection only specifies a condition on the _id
field
and returns only the _id
field, the _id
index can cover the
query when run against a mongos
even if the _id
field is not the shard key.
In previous versions, an index cannot cover
a query on a sharded collection when run against a
mongos
.
explain
To determine whether a query is a covered query, use the
db.collection.explain()
or the explain()
method and review the results.
For more information see Measure Index Use.