Memory management and cache optimization
Fundamentals of Memory Management
MongoDB's memory management directly impacts query performance and system stability. The WiredTiger storage engine defaults to using a memory-mapped file mechanism, mapping data files to memory address spaces. The storage.wiredTiger.engineConfig.cacheSizeGB
parameter can be configured to set the cache size, recommended at 50%-70% of physical memory. When the working set exceeds cache capacity, page swapping occurs. Cache hit rates can be monitored via db.serverStatus().wiredTiger.cache
:
// View cache usage
const cacheStats = db.serverStatus().wiredTiger.cache;
print(`Bytes read into cache: ${cacheStats['bytes read into cache']}`);
print(`Bytes written from cache: ${cacheStats['bytes written from cache']}`);
print(`Pages evicted: ${cacheStats['pages evicted']}`);
Working Set Optimization
The working set refers to the residency of active data in memory. Collection working set characteristics can be analyzed using db.collection.stats()
:
const stats = db.orders.stats();
print(`Working set size: ${stats.size} bytes`);
print(`Index size: ${stats.totalIndexSize} bytes`);
Optimization strategies include:
- Vertical sharding: Separate large fields into independent collections
- Hot data isolation: Store frequently accessed data in centralized locations
- Preloading: Use the
touch
command to load indexes at startup
Index Memory Optimization
Indexes are major memory consumers. Compound index design should follow the ESR principle:
- Equality (fields for equality queries come first)
- Sort (sort fields in the middle)
- Range (fields for range queries come last)
Example before optimization:
db.products.createIndex({ category: 1, price: 1, rating: -1 })
After optimization:
db.products.createIndex({ category: 1, rating: -1, price: 1 })
Be mindful of memory overhead when using hint()
to enforce indexes:
db.orders.find({ status: "shipped" })
.sort({ created_at: -1 })
.hint({ status: 1, created_at: -1 })
Query Memory Control
Use cursor.maxTimeMS()
and allowDiskUse
to control memory usage:
// Limit query memory usage
db.reports.aggregate([
{ $match: { year: 2023 } },
{ $group: { _id: "$department", total: { $sum: "$sales" } } }
], {
maxTimeMS: 30000,
allowDiskUse: true
})
For large result sets, use batch fetching:
const batchSize = 1000;
let cursor = db.logs.find().batchSize(batchSize);
while (cursor.hasNext()) {
const docs = cursor.next();
// Process documents
}
Write Memory Optimization
Batch inserts are 3-5 times more memory-efficient than single inserts:
// Inefficient approach
for (let i = 0; i < 1000; i++) {
db.measurements.insert({ value: Math.random() });
}
// Efficient approach
const bulk = db.measurements.initializeUnorderedBulkOp();
for (let i = 0; i < 1000; i++) {
bulk.insert({ value: Math.random() });
}
bulk.execute();
For updates, use $set
instead of full document replacement:
// Not recommended
db.users.update({ _id: 1 }, { name: "New", email: "new@example.com" });
// Recommended
db.users.update({ _id: 1 }, { $set: { name: "New", email: "new@example.com" } });
Connection Pool Tuning
Connection pool size affects memory usage and concurrent performance. Calculation formula:
Maximum connections = (Core count * 2) + Effective disk count
Configuration example:
# mongod.conf
net:
maxIncomingConnections: 500
serviceExecutor: "adaptive"
Monitor connection usage:
const connStats = db.serverStatus().connections;
print(`Available connections: ${connStats.available}`);
print(`Current in use: ${connStats.current}`);
Operating System-Level Optimization
Linux systems require kernel parameter adjustments:
# Increase memory page size
sysctl -w vm.nr_hugepages=1024
# Adjust dirty page ratios
sysctl -w vm.dirty_ratio=20
sysctl -w vm.dirty_background_ratio=5
Use cgroups to limit MongoDB memory:
cgcreate -g memory:mongodb
cgset -r memory.limit_in_bytes=16G mongodb
Monitoring and Diagnostic Tools
Real-time monitoring tools:
// Current memory status
db.currentOp(true).inprog.forEach(op => {
if(op.memUsage) print(`Op ${op.opid} using ${op.memUsage}MB`);
});
// Periodic sampling
setInterval(() => {
const mem = db.serverStatus().mem;
print(`Resident: ${mem.resident}MB Virtual: ${mem.virtual}MB`);
}, 5000);
Use mongotop
and mongostat
to analyze hotspots:
mongotop --host localhost --rows 5 --seconds 3
mongostat --host localhost --discover --all
Sharded Cluster Memory Management
Special considerations for sharded clusters:
- Config servers: Maintain small working sets
- Query routers: Increase mongos memory
- Data shards: Balance shard distribution
Check shard balance status:
db.adminCommand({ balancerStatus: 1 });
db.adminCommand({ getShardDistribution: "db.collection" });
Adjust chunk size to impact memory usage:
db.settings.update(
{ _id: "chunksize" },
{ $set: { value: 64 } },
{ upsert: true }
);
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn