当索引超5个时,wiredtiger缓存压力剧增致延迟上升、吞吐下降;需用serverstatus查cache使用率>85%并遍历各集合索引数定位问题,冗余索引还导致查询失准与写放大。

当集合查询模式稳定但响应延迟开始上升、写入吞吐量明显下滑时,首先要检查单集合索引数量是否超过五个——这不是经验猜测,而是 WiredTiger 缓存机制与 B-Tree 维护开销共同决定的硬性分水岭。
内存缓存被低效索引持续挤占
WiredTiger 不按需加载索引页,而是预热整棵 B-Tree 的内部节点;单集合每多建一个索引,就多一棵独立树要驻留内存。实测表明:5 个以上索引时,【cache 使用率长期 >85% 就极大概率由索引引发】,此时真正服务查询的热数据页被迫换出,反而加剧随机访问延迟。
用 db.serverStatus().cache 查看 bytes currently in the cache 与 maximum bytes configured 比值,若持续高于 0.85,再执行 db.getCollectionNames().forEach(c => print(c + ': ' + db.getCollection(c).getIndexes().length)),就能快速定位超标集合。
特别注意:totalSize 小的索引未必省内存——深度 ≥6 或 internalPages 占比 >40% 的索引,实际内存驻留可能达磁盘体积的 3 倍以上。
写入性能因同步更新指数级衰减
方法一:插入/更新一条文档时,MongoDB 必须原子性地刷新所有匹配字段的索引条目。索引从 4 个增至 6 个,写放大不是+50%,而是触发更多页分裂与锁等待。
方法二:复合索引 {a:1,b:1} 和单字段索引 {a:1} 并存时,a 字段变更会强制刷两次索引页;若再叠加 {a:1,createdAt:-1},-1 方向索引更易页分裂,写放大进一步恶化。
【批量导入前务必执行 db.collection.dropIndexes()】,导入完成后再重建必要索引,实测速度提升 3–5 倍——这步跳过,等于主动把写入瓶颈焊死在流程里。
查询计划被冗余索引干扰失准
第一步:运行 db.collection.find({status:"paid"}).explain("executionStats"),观察 executionStages.stage 是否为 IXSCAN;
第二步:核对 keysExamined 与 nReturned 比值,若达 500:1,说明该索引区分度极差,已沦为无效占位符;
第三步:检查 indexDetails. 注意:_id 索引天然高效,但其他索引若只为 $in 或三值枚举字段(如 status ∈ ["pending","paid","failed"])单独建立,基本无法进入高频命中路径。











