tencent cloud

TencentDB for MongoDB

문서TencentDB for MongoDBDevelopment SpecificationsPerformance Optimization and Troubleshooting

Performance Optimization and Troubleshooting

Download
포커스 모드
폰트 크기
마지막 업데이트 시간: 2026-07-10 22:01:13
This document introduces performance optimization methods and common issue troubleshooting guidelines for Tencent Cloud MongoDB, covering topics such as performance analysis tool usage, common performance issue diagnosis, and development-phase checklists. It helps developers quickly locate and resolve performance issues during development and Ops.

Performance Issue Scenarios

In MongoDB production practices, performance optimization is a core component for ensuring system stability. As business volume grows, developers must possess the ability to quickly locate and troubleshoot performance bottlenecks. Common abnormal performance indicators include:
Query latency surges: slow log queries occur frequently, and response times deteriorate from milliseconds to seconds or even minutes.
CPU is under sustained high load: the database instance's CPU utilization remains persistently high, causing a cliff-like drop in system response.
Memory is under pressure: the WiredTiger engine's cache hit ratio decreases, the Eviction mechanism is frequently triggered, and query jitter occurs.
Disk I/O encounters a bottleneck: read/write throughput reaches the physical limit, and operations are severely backlogged in the queue.
The number of connections is overloaded/exhausted: the connection pool is full, causing new requests to be rejected as they cannot establish connections.
This document systematically describes how to identify and efficiently resolve the aforementioned core performance pain points by using performance analysis tools.

Performance Analysis Tools

explain() Execution Plan Analysis

explain() is the most important performance analysis tool in MongoDB, used to analyze the execution plan and performance metrics of queries. The three modes of explain():
Mode
Description
Application Scenario
queryPlanner (default)
Returns only the query plan, without executing the query.
Quickly view the plan selected by the optimizer.
executionStats
Executes the query and returns statistics.
Analyze query actual performance.
allPlansExecution
Executes all candidate plans and returns information.
In-depth analysis of optimizer decisions.

Basic Usage

// Query plan
db.t_orders.find({ status: "paid" }).explain()

// Execute statistics
db.t_orders.find({ status: "paid" }).explain("executionStats")

// All plan execution information
db.t_orders.find({ status: "paid" }).explain("allPlansExecution")

Key Metric Interpretation

{
"queryPlanner": {
"winningPlan": {
"stage": "FETCH", // Execution stage
"inputStage": {
"stage": "IXSCAN", // Uses index scan
"keyPattern": { "status": 1 },
"indexName": "idx_status",
"direction": "forward"
}
},
"rejectedPlans": [...] // Rejected plans
},
"executionStats": {
"executionSuccess": true,
"nReturned": 1000, // Number of documents returned
"executionTimeMillis": 15, // Execution time (milliseconds)
"totalKeysExamined": 1000, // Number of index entries scanned
"totalDocsExamined": 1000, // Number of documents scanned
"executionStages": {
"stage": "FETCH",
"nReturned": 1000,
"docsExamined": 1000,
"inputStage": {
"stage": "IXSCAN",
"nReturned": 1000,
"keysExamined": 1000
}
}
}
}

Execution Stage Description

Stage
Description
Ideal or Not
COLLSCAN
Full Table Scan
Index creation required
IXSCAN
Index scanning
Ideal
FETCH
Fetch documents by returning to the table via index.
Normal
SORT
In-memory sorting
Create an index for the sort field.
SORT_KEY_GENERATOR
Generate sort keys.
Appears in conjunction with SORT
PROJECTION_COVERED
Covered index projection
Ideal (no table lookup required)
PROJECTION_SIMPLE
Simple projection
Normal
LIMIT
Limit the number of returned results.
Normal
SKIP
Skip documents.
Normal (inefficient during deep pagination)
SHARD_MERGE
Shard result merging
Normal (in a sharded cluster)
SINGLE_SHARD
Single-shard query
Targeted query

Performance Metric Evaluation Criteria

Metric
Ideal Value
Requires Optimization
totalDocsExamined / nReturned
≈ 1
> 10 (excessive document scanning)
totalKeysExamined / nReturned
≈ 1
> 10 (low index efficiency)
executionTimeMillis
< 100ms
> 1000ms (requires optimization)
stage
IXSCAN
COLLSCAN (missing index)
SORT Stage or Not
None.
Yes (in-memory sorting)

Slow Log Query Analysis

MongoDB automatically logs slow log queries whose execution time exceeds a threshold, which serves as a crucial basis for troubleshooting performance issues.

Slow Log Query Configuration

// View the current slow log query threshold
db.getProfilingStatus()
// { "was": 1, "slowms": 100 }

// Set the slow log query threshold to 200 ms
db.setProfilingLevel(1, { slowms: 200 })

// level 0: Disable
// level 1: Log only slow log queries
// level 2: Log all operations (Use with caution, as it has a significant performance impact)

Querying Slow Log Queries

You can log in to the console and directly search and analyze slow logs on the Slow Log Query page. For detailed operations, see Slow Log Query.

Monitoring Current Operations with currentOp

currentOp can capture a real-time snapshot of all active operations currently being executed in the database, making it suitable for troubleshooting current performance issues.
// View all current operations
db.currentOp()

// View operations whose execution time exceeds 5 seconds
db.currentOp({
"active": true,
"secs_running": { "$gt": 5 }
})

// View operations that are waiting for locks
db.currentOp({
"waitingForLock": true
})

// View operations for a specific collection
db.currentOp({
"ns": "mydb.t_orders"
})


// Terminate operations whose execution time exceeds 10 seconds
db.currentOp().inprog.forEach(function(item){if(item.secs_running > 10 )db.killOp(item.opid)})

serverStatus Monitoring Metrics

serverStatus is used to obtain a global status snapshot and counter information for a MongoDB instance.
db.serverStatus()

// Key metrics to focus on
{
"connections": {
"current": 50, // current number of connections
"available": 950, // number of available connections
"totalCreated": 1000
},
"opcounters": {
"insert": 10000,
"query": 50000,
"update": 5000,
"delete": 1000
},
"mem": {
"resident": 4096, // resident memory (MB)
"virtual": 8192 // virtual memory (MB)
},
"wiredTiger": {
"cache": {
"bytes currently in the cache": ...,
"maximum bytes configured": ...
}
}
}

Common Performance Issue Diagnosis

Full Table Scan (COLLSCAN)

Problem Manifestation

When you execute explain() to analyze the query plan, the stage is displayed as "COLLSCAN".
Query latency increases linearly with the amount of data in the collection.
CPU utilization and disk I/O load increase significantly.

Troubleshooting steps

// 1. Confirm whether a full table scan is performed
db.t_orders.find({ status: "paid" }).explain("executionStats")
// Check whether winningPlan.stage is COLLSCAN

// 2. Check existing indexes
db.t_orders.getIndexes()

// 3. Create appropriate indexes
db.t_orders.createIndex({ status: 1 }, { background: true })

// 4. Verify that the index takes effect
db.t_orders.find({ status: "paid" }).explain("executionStats")
// Confirm that the stage has changed to IXSCAN

Common Causes

Cause
Solution
Missing index
Create an index for the query condition field.
Query conditions do not match the index.
Adjust the query or create a suitable composite index.
Using operators that cannot leverage indexes.
Avoid using $ne, $nin, prefixless regular expressions, and similar operators.
Low index selectivity
Create a composite index to improve selectivity.

Memory Sorting Exceeding Limits

Problem Manifestation

The database returns an error: Sort operation used more than the maximum 33554432 bytes of RAM.
When you execute explain() to analyze the query plan, a "SORT" stage is shown.

Troubleshooting steps

// 1. Confirm whether an in-memory sort is performed
db.t_orders.find({ status: "paid" }).sort({ createTime: -1 }).explain("executionStats")
// Check whether a SORT stage exists

// 2. Create an index that supports sorting
db.t_orders.createIndex({ status: 1, createTime: -1 }, { background: true })

// 3. Verify index sorting
db.t_orders.find({ status: "paid" }).sort({ createTime: -1 }).explain("executionStats")
// Confirm that no SORT stage exists

Solution

Solution
Description
Create index (recommended)
Create an index for the sort field. Index sorting has no memory limit.
Reduce the amount of data to be sorted
Add filter conditions to reduce the number of documents that need to be sorted.
Pagination optimization
Use cursor-based pagination on the sort field to replace deep pagination (skip+sort). For details, see Avoid Deep Pagination.
Temporary solution
Use allowDiskUse (poor performance).

Hot Data and Hot Shards

Problem Manifestation

In a sharded cluster, the CPU load, I/O load, or storage space usage of a specific shard is significantly higher than that of other shards.
Write traffic (QPS) is concentrated on a single shard, while other shards remain idle.
Chunks are frequently migrated within the cluster, but the data imbalance among shards is not effectively improved.

Troubleshooting steps

// 1. View the shard data distribution
db.t_orders.getShardDistribution()

// 2. View the chunk distribution
db.getSiblingDB("config").chunks.aggregate([
{ $match: { ns: "mydb.t_orders" } },
{ $group: { _id: "$shard", count: { $sum: 1 } } }
])

// 3. Check the shard key selection
db.getSiblingDB("config").collections.findOne({ _id: "mydb.t_orders" })

Common Causes and Solutions

Cause
Solution
The shard key is a monotonically increasing field.
Use Hash sharding or composite shard keys.
Low shard key cardinality
Select high-cardinality fields or composite keys.
Write operations concentrated on the latest data.
Use timestamp-based Hash sharding.
Frequent access to certain hot values.
Cache hot data at the business layer.

Connection Pool Exhaustion

Problem Manifestations:
Client or application logs throw an error: connection pool exhausted.
The database instance rejects new client connection requests, causing new connections to fail to be established.
A large number of database requests from the application side time out because they are waiting for connections.
Troubleshooting Steps:
// 1. View the current number of connections
db.serverStatus().connections
// { "current": 950, "available": 50, "totalCreated": 10000 }

// 2. View the connection sources
db.currentOp(true).inprog.forEach(function(op) {
if (op.client) print(op.client);
})

// 3. Check the application connection pool configuration
// Confirm whether the maxPoolSize setting is appropriate
Solutions:
Solution
Description
Optimize connection pool.
Reduce the maxPoolSize for a single application.
Check for connection leaks.
Ensure that connections are released properly.
Increase instance specification.
Increase the maximum number of connections supported by an instance.
Reduce application instances.
Reduce the total connection demand.

Lock Waits and Deadlocks

Problem Manifestation

The response time for the database as a whole or for specific operations exhibits significant fluctuations and unstable performance.
When currentOp() is executed, a large number of operations in the results are in a waiting state with waitingForLock: true.
Some reads and writes remain suspended for a long time and cannot return execution results promptly.

Troubleshooting steps

// 1. View operations in lock waiting
db.currentOp({ "waitingForLock": true })

// 2. View operations that hold locks for a long time
db.currentOp({
"active": true,
"secs_running": { "$gt": 10 }
})

// 3. View the lock status
db.serverStatus().locks

Solution

Cause
Solution
Long transactions
Shorten transaction execution time and split large transactions.
Long-running queries
Optimize queries and add indexes.
Creating indexes in the foreground
Use background:true.
DDL operations
Schedule execution during off-peak hours.

Development Phase Checklist

SQL Review Checklist Before Launch

Query Statement Review

Check Item
Verification Method
Passing Criteria
Query uses indexes
explain("executionStats")
The stage is IXSCAN.
No in-memory sorting
explain("executionStats")
No SORT stage
Scan efficiency
totalDocsExamined/nReturned
The ratio is close to 1.
Minimize returned fields.
Check whether projection is used.
Only necessary fields are returned.
Reasonable pagination method
Check pagination implementation.
Cursor-based pagination on the sort field

Write Statement Review

Check Item
Verification Method
Passing Criteria
Conditional Update
Code review
Prohibit Update Without Condition.
Update Using $set
Code review
Prohibit Full Document Replacement.
Batch Operations with Controls
Code review
Batch Size ≤ 1000 Items
Write Concern appropriateness or not
Code review
Use `majority` for core business.

Index Coverage Review

Checking Whether Existing Indexes Meet Query Requirements

// List all indexes
db.t_orders.getIndexes()

// Check index usage statistics
db.t_orders.aggregate([{ $indexStats: {} }])

// Verify index coverage for the primary queries
const mainQueries = [
{ status: "paid" },
{ customerId: "C001", createTime: { $gte: ISODate("2024-01-01") } },
{ orderId: "ORD001" }
];

mainQueries.forEach(query => {
const plan = db.t_orders.find(query).explain("executionStats");
print("Query:", JSON.stringify(query));
print("Stage:", plan.queryPlanner.winningPlan.stage);
print("DocsExamined:", plan.executionStats.totalDocsExamined);
print("---");
});

도움말 및 지원

문제 해결에 도움이 되었나요?

피드백