Best practices and common issue troubleshooting
Best Practices
Index Optimization
In MongoDB, proper index design can significantly improve query performance. The order of compound indexes follows the ESR principle (Equality, Sort, Range):
- Fields for equality queries come first
- Sort fields are placed in the middle
- Range query fields are placed last
// Good index example
db.orders.createIndex({
userId: 1, // Equality
createDate: -1, // Sort
amount: 1 // Range
})
Avoid over-indexing, as each additional index increases write overhead. Use explain()
to analyze query execution plans:
db.orders.find({
userId: "user123",
createDate: { $gt: ISODate("2023-01-01") }
}).sort({ amount: 1 }).explain("executionStats")
Document Design
Choose between embedding or referencing based on query patterns:
- One-to-few relationships with frequent joint queries are suitable for embedding
- One-to-many relationships or independently accessed data are suitable for referencing
// Embedded document example (suitable for blog posts and comments)
{
_id: "post1",
title: "MongoDB Guide",
comments: [
{ user: "Alice", text: "Great article", date: ISODate(...) },
{ user: "Bob", text: "Very helpful", date: ISODate(...) }
]
}
// Reference example (suitable for users and orders)
// users collection
{ _id: "user1", name: "John" }
// orders collection
{ _id: "order1", userId: "user1", items: [...] }
Write Optimization
Use bulkWrite()
for batch operations instead of single writes:
const bulkOps = [
{ insertOne: { document: { name: "Product A", price: 100 } } },
{ updateOne: {
filter: { name: "Product B" },
update: { $set: { price: 200 } }
}},
{ deleteOne: { filter: { name: "Product C" } }}
];
db.products.bulkWrite(bulkOps);
Set appropriate write concern levels to balance data safety and performance:
// Majority node confirmation for writes
db.products.insertOne(
{ name: "New Product", stock: 50 },
{ writeConcern: { w: "majority", j: true } }
)
Common Issue Troubleshooting
Performance Issues
Slow queries are typically caused by:
- Missing or improper indexes
- Full collection scans
- In-memory sorts (sorts that cannot use indexes)
Use db.currentOp()
to view ongoing operations:
// View operations running longer than 3 seconds
db.currentOp({
"active": true,
"secs_running": { "$gt": 3 }
})
Monitor database activity with mongotop
and mongostat
:
mongotop --host localhost:27017
mongostat --host localhost:27017 --rowcount 5
Connection Issues
Connection pool exhaustion manifests as applications being unable to acquire new connections. Adjust connection pool size:
// Node.js driver example
const client = new MongoClient(uri, {
poolSize: 50, // Connection pool size
connectTimeoutMS: 30000, // Connection timeout
socketTimeoutMS: 60000 // Socket timeout
});
Check connection status:
db.serverStatus().connections
// Example output
{
"current" : 25,
"available" : 475,
"totalCreated" : 42
}
Memory Usage
MongoDB tends to use all available memory as cache. Monitor memory usage:
db.serverStatus().mem
// Typical output
{
"bits" : 64,
"resident" : 1024, // Resident memory (MB)
"virtual" : 2048, // Virtual memory (MB)
"supported" : true
}
When memory pressure occurs:
- Check if the working set exceeds physical memory
- Add more RAM
- Optimize queries to reduce memory usage
Replica Set Issues
Common replication delay causes:
- Insufficient network bandwidth
- Underpowered secondary nodes
- High write load on primary node
Check replication status:
rs.printReplicationInfo()
rs.printSecondaryReplicationInfo()
// Detailed status
rs.status()
Handling replication delays:
- Increase
oplog
size - Upgrade secondary node configurations
- Limit primary node write rate
Sharded Cluster Issues
Common sharded cluster issues include:
- Uneven data distribution
- Queries not including shard keys
- High configuration server load
Check data distribution:
db.collection.getShardDistribution()
Balancer status check:
sh.isBalancerRunning()
sh.getBalancerState()
Shard key selection principles:
- High cardinality (many distinct values)
- Even write distribution
- Matches query patterns
Lock Contention
MongoDB uses multi-granularity locking. View lock status:
db.currentOp({ "waitingForLock": true })
db.serverStatus().locks
Methods to reduce lock contention:
- Shorten transaction duration
- Avoid full collection scans
- Use appropriate write concern levels
Transaction Handling
Multi-document transaction considerations:
- Maximum transaction runtime of 60 seconds
- Limit on total operations in a transaction
- Avoid creating collections within transactions
Transaction example:
const session = client.startSession();
try {
session.startTransaction({
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" }
});
await accounts.updateOne(
{ _id: "A" }, { $inc: { balance: -100 } },
{ session }
);
await accounts.updateOne(
{ _id: "B" }, { $inc: { balance: 100 } },
{ session }
);
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
Storage Engine Issues
WiredTiger engine tuning:
// View storage engine status
db.serverStatus().wiredTiger
// Adjust cache size (in configuration file)
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 2
Compression configuration:
storage:
wiredTiger:
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
Query Optimizer
The MongoDB query optimizer may choose non-optimal execution plans. Force using specific indexes:
db.orders.find({ userId: "123", status: "A" })
.hint({ userId: 1, status: 1 })
Rebuild indexes:
db.orders.reIndex()
Date Handling
Common date query issues include timezone handling and format conversion:
// Query documents for a specific date (UTC time)
db.events.find({
date: {
$gte: ISODate("2023-01-01T00:00:00Z"),
$lt: ISODate("2023-01-02T00:00:00Z")
}
})
// Use aggregation to convert timezones
db.events.aggregate([
{
$project: {
localDate: {
$dateToString: {
format: "%Y-%m-%d %H:%M",
date: "$date",
timezone: "+08:00"
}
}
}
}
])
Array Operations
Common array query and update issues:
// Query arrays containing specific elements
db.products.find({ tags: "electronics" })
// Update specific elements in arrays
db.products.updateOne(
{ _id: 1, "variants.id": "v1" },
{ $set: { "variants.$.price": 19.99 } }
)
// Use $elemMatch for multiple condition queries
db.survey.find({
results: {
$elemMatch: {
product: "xyz",
score: { $gte: 8 }
}
}
})
Security Configuration
Common security configuration issues:
- Authentication not enabled
- Weak passwords
- Network exposure
Basic security configuration:
security:
authorization: enabled
keyFile: /path/to/keyfile
net:
bindIp: 127.0.0.1,192.168.1.100
port: 27017
Create users:
db.createUser({
user: "admin",
pwd: passwordPrompt(), // or plaintext password
roles: [
{ role: "userAdminAnyDatabase", db: "admin" },
{ role: "readWriteAnyDatabase", db: "admin" }
]
})
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn