wiredtiger缓存是否够用需对比配置值与实时使用量,若后者长期超85%则不足;workingset非索引体积而是热数据估算,应结合查询模式与page.faults判断索引页驻留情况。

WiredTiger缓存大小是否够用?看 wiredTiger.cache.maximum.bytes.configured
MongoDB默认把WiredTiger缓存设为“50%物理内存或1GB,取小值”,这在小机器上很容易不够。缓存不足时,索引页频繁进出内存,workingSet远大于缓存,就会拖慢查询。
- 查当前配置:
db.serverStatus().wiredTiger.cache["maximum bytes configured"] - 查实时使用:
db.serverStatus().wiredTiger.cache["bytes currently in the cache"] - 如果后者长期接近前者(比如 >85%),说明缓存吃紧,索引很难常驻
- 调整方式:启动时加
--wiredTigerCacheSizeGB 4(单位是GB,不能带小数点后太多位)
working set到底有多大?别只信 db.serverStatus().metrics.wiredTiger.cache.workingSetPages
这个字段返回的是“估算页数”,不是字节数,而且只反映最近访问的热数据范围,不等于真实索引体积。它容易被误读为“索引大小”,其实只是活跃数据的粗略投影。
- 更靠谱的做法:用
db.collection.stats().size+.totalSize粗估数据+索引总占空间 - 再结合
db.collection.getIndexes()查每个索引的size字段(注意:只有执行过collStats并开启详细统计才准) - 真正决定是否常驻的是“热索引页”是否能塞进缓存——所以得看查询模式:高频查询的索引字段组合,比大但冷的索引更需要内存
怎么确认某个索引页真在内存里?db.collection.explain("executionStats") 看 totalDocsExamined 和 totalKeysExamined
如果一次查询触发大量磁盘读(executionStats.executionTimeMillis 高,且 executionStats.nReturned 远小于 totalKeysExamined),大概率索引页不在缓存中,WiredTiger被迫从磁盘加载。
- 重点看
executionStats.allPlansExecution里的stage: "IXSCAN"节点是否有docsExamined异常高 - 配合
mongostat --host localhost:27017观察netIn、netOut和page.faults:持续有 page faults 就说明缓存没兜住 working set - 注意:即使索引建了,如果查询条件没用上索引前缀,WiredTiger也不会预热对应页——索引常驻的前提是被真正访问过
索引常驻 ≠ 全量加载:WiredTiger按需加载页,但淘汰策略很激进
WiredTiger不会一启动就把所有索引页塞进缓存,而是按查询访问路径逐步加载;但一旦缓存压力大,它会优先淘汰“最近最少使用”的页,不管是不是索引页。所以高频索引也可能被踢出去。
- 没有“锁定索引到内存”的机制,
touch命令(如db.runCommand({ touch: "collection", data: true, index: true }))只能预热一次,不能保活 - 真正稳定常驻的办法只有两个:缓存足够大(> working set),或者让查询足够规律(使热点页反复命中,自然留在LRU头部)
- 最容易被忽略的一点:副本集 secondary 节点如果开启
readPreference=secondary,它的 working set 可能和 primary 完全不同——别直接套用主节点的缓存经验










