在解决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+异地存储),确保数据安全。