Optimizing MongoDB Query Performance with Indexing
Introduction
Indexing is a powerful way to improve the performance of your MongoDB queries. Without indexes, MongoDB must scan every document in a collection to find the ones that match the query, which can be slow. In this blog, we will create an index on a field, analyze the query performance before and after indexing, and see how much improvement it provides.
Prerequisites
- Basic understanding of MongoDB.
- MongoDB installed on your machine or access to a cloud service like MongoDB Atlas.
Step 1: Create a MongoDB Collection and Insert Documents
We’ll start by creating a collection called users
and inserting some sample documents to work with.
Inserting Sample Documents
db.users.insertMany([
{ name: "Alice", age: 28, city: "New York" },
{ name: "Bob", age: 34, city: "Los Angeles" },
{ name: "Charlie", age: 22, city: "Chicago" },
{ name: "Diana", age: 29, city: "New York" },
{ name: "Ethan", age: 42, city: "Los Angeles" },
{ name: "Frank", age: 30, city: "San Francisco" },
{ name: "George", age: 38, city: "Austin" }
]);
Step 2: Measure Query Performance Before Indexing
Let’s start by measuring the query performance before creating an index. We’ll use the explain()
method to get query execution stats.
Query Example
Let’s run a query to find all users whose age is 30 or more.
db.users.find({ age: { $gte: 30 } }).explain("executionStats")
This will return a detailed execution plan. Look for the following in the output:
- Total Documents Examined: This shows how many documents MongoDB had to scan.
- Execution Time: This gives the total time it took to execute the query.
Example Output Before Indexing
{
"executionStats": {
"nReturned": 3,
"totalDocsExamined": 7,
"executionTimeMillis": 2
}
}
Here, MongoDB had to examine all 7 documents to return the 3 that matched our query, and it took 2 milliseconds.
Step 3: Create an Index on the Age Field
To improve query performance, let’s create an index on the age
field.
Create Index
db.users.createIndex({ age: 1 })
This command creates an ascending index on the age
field. The 1
indicates ascending order. You could also create a descending index by using -1
.
Step 4: Measure Query Performance After Indexing
Now, let’s run the same query again and measure the performance after the index is created.
Query After Indexing
db.users.find({ age: { $gte: 30 } }).explain("executionStats")
Example Output After Indexing
{
"executionStats": {
"nReturned": 3,
"totalDocsExamined": 3,
"executionTimeMillis": 0
}
}
After indexing, MongoDB examined only 3 documents (those that matched the age >= 30
condition) and executed the query in 0 milliseconds! This is a significant improvement over the previous scan of all 7 documents.
Step 5: Verifying the Index
To verify that the index has been created, you can list all indexes on the users
collection using the getIndexes()
method:
db.users.getIndexes()
This will display all the indexes, including the one we created on the age
field.
Example Output
[
{
"v": 2,
"key": { "_id": 1 },
"name": "_id_",
"ns": "my_database.users"
},
{
"v": 2,
"key": { "age": 1 },
"name": "age_1",
"ns": "my_database.users"
}
]
You can see that an index named "age_1"
has been created on the age
field.
Conclusion
In this blog post, we explored how to create an index in MongoDB to improve query performance. We demonstrated the significant improvement in query execution time after indexing the age
field. Indexes are a powerful tool in MongoDB, especially when dealing with large datasets, as they reduce the number of documents MongoDB needs to scan to find matching documents.