应检查索引树深度≥6、内部页占比>15%及wiredtiger缓存占用超90%,若同时存在则该索引因结构膨胀持续挤占内存;再结合mongostat中getmores异常升高或慢查询集中于该索引,即可确认其为内存压力主因。

要判断MongoDB中某个索引是否因体积过大而持续挤占WiredTiger缓存空间,不能只看磁盘上的索引大小,必须结合索引树结构在内存中的实际驻留状态来验证——因为WiredTiger会主动加载非叶子页,而这些页一旦堆积,就会直接推高resident内存并触发频繁换页。
查索引树深度与内部页占比
连接到目标数据库后,执行:
db.collection.stats({indexDetails: true})
在返回结果中定位你要评估的索引名(如status_1_createdAt_-1),展开其indexDetails.
① depth:B-Tree深度。≥6时需警惕,深度每+1,单次查询至少多一次内存随机访问;
② internalPages:内部节点页数量;
③ entries:总键值对数。用 internalPages ÷ (internalPages + leafPages) 算出内部页占比——【若 > 15%】,说明索引结构稀疏、存在页分裂积压,已开始显著增加缓存压力。
比对WiredTiger缓存实时占用率
运行:
db.runCommand({serverStatus: 1}).wiredTiger.cache
提取两个关键数值:
maximum bytes configured(例如8 GB)和
bytes currently in the cache(当前缓存实际用量)。
如果后者长期稳定在前者的90%以上(比如7.3 GB+),且同期pages evicted by application threads数值明显上升,说明缓存已近饱和——此时再叠加高internalPages占比的索引,就是内存压力的直接推手。
观察索引页是否频繁换入换出
方法一:用mongostat实时盯控
mongostat --host
重点看net列中getmores值。若该值持续高于正常基线(例如突增3倍以上),而查询QPS未同步上涨,大概率是索引页未能常驻缓存,导致每次游标拉取都要重新加载页。
方法二:检查慢查询是否集中于特定索引字段
启用数据库慢日志(db.setProfilingLevel(1, {slowms: 100})),然后查profile集合:
db.system.profile.find({ns: "db.collection", millis: {$gt: 100}}).sort({ts: -1}).limit(5)
若多数慢操作都命中同一个复合索引,且该索引的indexDetails.tree.depth ≥ 6,基本可锁定问题索引。











