在解决MongoDB性能问题前,需先通过监控工具和日志分析定位瓶颈根源:
mongostat
查看读写操作、内存使用、连接数等实时指标;mongotop
分析集合级别的读写时间分布,快速定位慢操作集合。db.setProfilingLevel(1, {slowms: 100})
开启慢查询记录(阈值设为100ms),用db.profile()
查看慢查询详情,识别未走索引或执行效率低的查询。top
监控CPU使用率(若CPU占用过高,可能是查询复杂或索引缺失);iostat -x 1
查看磁盘IO(若await
或%util
过高,说明磁盘成为瓶颈);free -h
检查内存使用(若available
内存不足,可能导致频繁换页)。瓶颈表现:CPU占用持续高位(>80%)、内存不足(available
内存<总内存的20%)、磁盘IO延迟高(await
>50ms)。
解决措施:
storage.wiredTiger.engineConfig.cacheSizeGB
设置为物理内存的70%-80%)。deadline
,HDD设为noop
),减少IO等待;禁用atime
(noatime,nodiratime
)降低元数据写入开销。瓶颈表现:查询执行时间长(如find
、aggregate
操作慢)、explain()
结果显示“COLLSCAN”(全表扫描)。
解决措施:
find
、sort
、aggregate
中频繁使用的字段创建索引(如db.collection.createIndex({user_id: 1, create_time: -1})
);复合索引需将选择性高的字段(如user_id
)放在前面,减少索引大小。db.collection.getIndexes()
审查索引,删除未使用的索引(通过$indexStats
查看accesses.ops
为0的索引)。db.collection.find({status: "active"}, {name: 1, age: 1})
,若索引包含status
、name
、age
,则无需访问文档)。瓶颈表现:查询返回大量不必要的数据、复杂查询(如多层嵌套$lookup
)执行慢。
解决措施:
find({}, {name: 1, age: 1, _id: 0})
仅返回需要的字段,减少网络传输和内存占用。$ne
、$not
)、正则表达式(如/^abc/
,除非是前缀匹配),这类条件无法有效利用索引。find
再group
),减少数据往返次数;合理使用$match
(尽早过滤数据)、$project
(减少字段)优化管道性能。bulkWrite
替代单条插入/更新(如批量插入1000条数据),减少网络通信次数。瓶颈表现:文档过大(超过16MB)、频繁的$lookup
操作、过度规范化(导致大量JOIN)。
解决措施:
$lookup
操作(关联查询性能较低)。瓶颈表现:缓存命中率低(WiredTiger缓存未充分利用)、连接数过多导致资源耗尽。
解决措施:
mongod.conf
中设置storage.wiredTiger.engineConfig.cacheSizeGB
为物理内存的70%-80%(如128GB内存设为80GB),确保常用数据缓存在内存中。net.maxIncomingConnections
(默认10000)和net.maxOutgoingConnections
(默认10000),根据应用需求增加连接数;同时用ulimit -n 64000
提高系统文件描述符限制,避免连接过多导致“Too many open files”错误。operationProfiling.mode: "slowOp"
(慢查询模式)或"all"
(全量模式),监控慢操作并针对性优化。瓶颈表现:单节点数据量过大(超过TB级)、数据分布不均(分片键选择不当)、副本集同步延迟。
解决措施:
user_id
)、查询频繁的字段作为分片键,避免数据倾斜(如避免用status
作为分片键,因大部分文档状态相同)。user_id
哈希分片),提高横向扩展能力;分片后需监控各分片的负载(如sh.status()
查看数据分布)。oplog
大小(replication.oplogSizeMB
),避免oplog
过小导致同步延迟。db.reIndex()
重建索引(优化索引碎片);每月备份数据(使用mongodump
+异地存储),确保数据安全。