Execution plan (explain) and query performance analysis
Basic Concepts of Execution Plans (explain)
MongoDB's explain()
method is a powerful diagnostic tool that reveals the execution details of a query. By appending .explain()
to a query statement, you can obtain the execution plan chosen by the query optimizer. The execution plan contains critical information about how the query is processed, including index usage, the number of documents scanned, execution time, and more.
// Basic usage example
db.collection.find({ name: "张三" }).explain()
Execution plans have three levels of detail:
queryPlanner
(default): Shows only the plan selected by the query optimizerexecutionStats
: Includes actual execution statisticsallPlansExecution
: Displays complete information for all candidate plans
Understanding Execution Plan Output
The core sections of the execution plan output include the following key information:
-
queryPlanner: Displays the query plan selected by the optimizer
winningPlan
: The chosen execution planrejectedPlans
: Rejected candidate plans
-
executionStats (when using this mode):
executionTimeMillis
: Total execution timetotalKeysExamined
: Number of index keys examinedtotalDocsExamined
: Number of documents examinednReturned
: Number of documents returned
// Example to get detailed execution statistics
db.orders.find({ status: "shipped" }).explain("executionStats")
Index Usage Analysis
Indexes are critical to query performance. The execution plan can confirm whether a query effectively uses indexes:
- IXSCAN: Indicates an index scan, which is ideal
- COLLSCAN: Indicates a full collection scan, which typically performs poorly
// Example of creating an index
db.products.createIndex({ category: 1, price: -1 })
// Checking index usage
db.products.find({
category: "electronics",
price: { $gt: 500 }
}).explain("executionStats")
When you see an IXSCAN
stage, you can check the indexName
to confirm which specific index was used. If you encounter COLLSCAN
, consider creating an appropriate index.
Key Query Performance Metrics
When analyzing an execution plan, pay special attention to the following metrics:
-
Query Selectivity:
- The ratio
nReturned / totalDocsExamined
should be as high as possible - Ideally, this ratio should be close to 1
- The ratio
-
Memory Usage:
- The
works
field indicates the workload of the operation advanced
indicates the number of documents returned early
- The
-
Stage Execution Order:
- MongoDB execution plans are structured as a tree of stages
- Child stages execute first, and their results are passed to parent stages
// Example of a compound query
db.users.find({
age: { $gt: 30 },
city: "北京",
lastLogin: { $gt: new Date("2023-01-01") }
}).explain("executionStats")
Diagnosing Common Performance Issues
-
Full Collection Scan (COLLSCAN):
- Symptom:
totalDocsExamined
is close to the total number of documents in the collection - Solution: Create an appropriate index for the query conditions
- Symptom:
-
Inefficient Index Usage:
- Symptom:
totalKeysExamined
is much larger thannReturned
- Solution: Optimize the index or query conditions
- Symptom:
-
In-Memory Sorting (SORT):
- Symptom: A
SORT
stage appears andmemLimit
is exceeded - Solution: Create an index for the sort field
- Symptom: A
// Example of an in-memory sorting issue
db.employees.find({ department: "IT" })
.sort({ salary: -1 })
.explain("executionStats")
Advanced Execution Plan Analysis Techniques
-
Index Intersection:
- MongoDB can use the intersection of multiple indexes
- The execution plan will show
AND_SORTED
orAND_HASH
stages
-
Covered Queries:
- When a query requires only indexed fields, it can avoid reading documents entirely
- Check if the
indexOnly
field is true
// Example of a covered query
db.customers.createIndex({ email: 1, name: 1 })
db.customers.find({ email: "user@example.com" }, { _id: 0, name: 1 })
.explain("executionStats")
- Query Shape Analysis:
- Queries with the same "shape" will reuse query plans
- Use
$planCacheStats
to view the plan cache
Practical Case Studies
Case 1: Product Search for an E-commerce Website
// Original query
db.products.find({
category: "electronics",
price: { $lte: 1000 },
rating: { $gte: 4 },
inStock: true
}).sort({ price: 1 }).explain("executionStats")
// Optimization: Create a compound index
db.products.createIndex({
category: 1,
inStock: 1,
rating: 1,
price: 1
})
Case 2: User Activity Query for a Social Media App
// Pagination query performance issue
db.posts.find({ userId: "user123" })
.sort({ createdAt: -1 })
.skip(100)
.limit(10)
.explain("executionStats")
// Optimization: Use range queries instead of skip
const lastDate = getLastDisplayedPostDate() // Get from the frontend
db.posts.find({
userId: "user123",
createdAt: { $lt: lastDate }
})
.sort({ createdAt: -1 })
.limit(10)
Execution Plans and Sharded Clusters
In a sharded environment, execution plan analysis becomes more complex:
- mergeSort: Results from different shards need to be merged and sorted
- shardFilter: Filters out data that doesn't match the shard key range
- clusterTime: Time overhead for coordination operations
// Example of a sharded cluster query
db.shardedCollection.find({
region: "APAC",
value: { $gt: 10000 }
}).explain("executionStats")
Pay special attention to the shards
field, which shows execution statistics for each shard. Uneven shard loads may indicate the need to adjust the sharding strategy.
Query Optimization Best Practices
-
Indexing Strategy:
- Follow the ESR rule (Equality-Sort-Range)
- Regularly review and remove unused indexes
-
Query Refactoring:
- Avoid using
$where
and$exists
- Limit the number of fields returned
- Avoid using
-
Monitoring Tools:
- Use
db.currentOp()
to monitor running queries - Configure slow query logs
- Use
// Set slow query threshold (in milliseconds)
db.setProfilingLevel(1, { slowms: 100 })
// View profiling results
db.system.profile.find().sort({ ts: -1 }).limit(10)
Execution Plans and Aggregation Pipelines
Analyzing execution plans for aggregation pipelines is more complex, as each stage can alter the data flow:
db.orders.aggregate([
{ $match: { status: "completed", date: { $gt: new Date("2023-01-01") } } },
{ $group: { _id: "$productId", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } },
{ $limit: 10 }
]).explain("executionStats")
Key points to observe:
- Pipeline optimization flags (e.g., early
$match
) - Input/output document counts for each stage
- Memory usage (especially for
$group
and$sort
stages)
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:索引的创建、查看与删除
下一篇:索引优化策略与常见问题