内存管理与缓存调优
内存管理基础
MongoDB的内存管理直接影响查询性能和系统稳定性。WiredTiger存储引擎默认使用内存映射文件机制,将数据文件映射到内存地址空间。通过storage.wiredTiger.engineConfig.cacheSizeGB
参数可配置缓存大小,建议设置为物理内存的50%-70%。当工作集超过缓存容量时会出现页面置换,可通过db.serverStatus().wiredTiger.cache
监控缓存命中率:
// 查看缓存使用情况
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']}`);
工作集优化
工作集指活跃数据在内存中的驻留情况。通过db.collection.stats()
可以分析集合的工作集特征:
const stats = db.orders.stats();
print(`Working set size: ${stats.size} bytes`);
print(`Index size: ${stats.totalIndexSize} bytes`);
优化策略包括:
- 垂直分片:将大字段分离到独立集合
- 热数据分离:将高频访问数据集中存放
- 预加载:启动时执行
touch
命令加载索引
索引内存优化
索引是内存消耗大户。复合索引设计应遵循ESR原则:
- Equality(等值查询字段在前)
- Sort(排序字段居中)
- Range(范围查询字段在后)
示例优化前:
db.products.createIndex({ category: 1, price: 1, rating: -1 })
优化后:
db.products.createIndex({ category: 1, rating: -1, price: 1 })
使用hint()
强制索引时需注意内存开销:
db.orders.find({ status: "shipped" })
.sort({ created_at: -1 })
.hint({ status: 1, created_at: -1 })
查询内存控制
通过cursor.maxTimeMS()
和allowDiskUse
控制内存使用:
// 限制查询内存使用
db.reports.aggregate([
{ $match: { year: 2023 } },
{ $group: { _id: "$department", total: { $sum: "$sales" } } }
], {
maxTimeMS: 30000,
allowDiskUse: true
})
对于大结果集应使用批量获取:
const batchSize = 1000;
let cursor = db.logs.find().batchSize(batchSize);
while (cursor.hasNext()) {
const docs = cursor.next();
// 处理文档
}
写入内存优化
批量插入比单条插入内存效率高3-5倍:
// 低效方式
for (let i = 0; i < 1000; i++) {
db.measurements.insert({ value: Math.random() });
}
// 高效方式
const bulk = db.measurements.initializeUnorderedBulkOp();
for (let i = 0; i < 1000; i++) {
bulk.insert({ value: Math.random() });
}
bulk.execute();
更新操作使用$set
而非全文档替换:
// 不推荐
db.users.update({ _id: 1 }, { name: "New", email: "new@example.com" });
// 推荐
db.users.update({ _id: 1 }, { $set: { name: "New", email: "new@example.com" } });
连接池调优
连接池大小影响内存占用和并发性能。计算公式:
最大连接数 = (核心数 * 2) + 有效磁盘数
配置示例:
# mongod.conf
net:
maxIncomingConnections: 500
serviceExecutor: "adaptive"
监控连接使用:
const connStats = db.serverStatus().connections;
print(`Available connections: ${connStats.available}`);
print(`Current in use: ${connStats.current}`);
操作系统级优化
Linux系统需要调整内核参数:
# 增加内存页大小
sysctl -w vm.nr_hugepages=1024
# 调整脏页比例
sysctl -w vm.dirty_ratio=20
sysctl -w vm.dirty_background_ratio=5
使用cgroups限制MongoDB内存:
cgcreate -g memory:mongodb
cgset -r memory.limit_in_bytes=16G mongodb
监控与诊断工具
实时监控工具:
// 当前内存状态
db.currentOp(true).inprog.forEach(op => {
if(op.memUsage) print(`Op ${op.opid} using ${op.memUsage}MB`);
});
// 定期采样
setInterval(() => {
const mem = db.serverStatus().mem;
print(`Resident: ${mem.resident}MB Virtual: ${mem.virtual}MB`);
}, 5000);
使用mongotop
和mongostat
分析热点:
mongotop --host localhost --rows 5 --seconds 3
mongostat --host localhost --discover --all
分片集群内存管理
分片集群需要特别关注:
- 配置服务器:保持小工作集
- 查询路由:增加mongos内存
- 数据分片:均衡分片分布
检查分片平衡状态:
db.adminCommand({ balancerStatus: 1 });
db.adminCommand({ getShardDistribution: "db.collection" });
调整chunk大小影响内存使用:
db.settings.update(
{ _id: "chunksize" },
{ $set: { value: 64 } },
{ upsert: true }
);
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn