mongo idx miss % 是索引未命中百分比,表示因无合适索引而全表扫描的查询比例,值越低越好,理想接近0;超过10%需排查,它由mongostat采样统计,非精确值,仅反映全局趋势。

mongo idx miss % 是什么,怎么看
它不是直接的“命中率”,而是 idx miss % —— 即索引未命中百分比,出现在 mongostat 输出中。值越低越好,理想是接近 0;超过 10% 就该查原因了。
运行 mongostat --host <hostname>:<port></port></hostname>(默认每秒刷新),注意这一列:它统计的是因找不到合适索引而被迫全表扫描的查询比例。但要注意:mongostat 是采样统计,不是精确计数,且只反映全局趋势,无法定位到具体集合或查询。
- 如果
idx miss %持续高于 5%,先检查是否有新上线的慢查询没走索引 -
mongostat默认不显示该列,需加-o参数(如mongostat -o "idx miss %")或确保终端宽度足够(SecureCRT 等需调最大列数 ≥150) - 该指标在 WiredTiger 引擎下更可信;MMAPv1 已弃用,不建议参考
用 db.currentOp() 和 explain() 定位未命中索引的查询
真正要优化,得找到具体哪条查询没走索引。db.currentOp() 能抓到正在执行的、耗时长且可能未命中索引的操作;配合 explain("executionStats") 可确认是否发生 COLLSCAN(全表扫描)。
例如,发现某查询慢,执行:
db.orders.find({ status: "pending", created_at: { $gt: ISODate("2026-07-01") } }).explain("executionStats")
重点看字段:
-
"executionPlan" → "stage": "COLLSCAN"表示没走索引 -
"nReturned"(返回数)远小于"totalDocsExamined"(扫描文档数),说明效率低下 -
"indexBounds"为空或缺失,基本确认无可用索引
启用 indexusage 采集器获取精确索引访问频次
mongostat 的 idx miss % 是估算值,真正想算“命中率 = 命中次数 / (命中 + 未命中)”,得靠 MongoDB Exporter 的 indexusage 指标。
部署 mongodb-exporter 时,确保启动参数含 --collect=indexusage 或配置文件中开启 indexusage: true。之后 Prometheus 会暴露指标如:
mongodb_mongod_index_counters_accesses_total{collection="orders",index="status_1_created_at_-1"}mongodb_mongod_index_counters_misses_total{collection="orders"}
用 PromQL 计算近 5 分钟命中率:
rate(mongodb_mongod_index_counters_accesses_total[5m]) / (rate(mongodb_mongod_index_counters_accesses_total[5m]) + rate(mongodb_mongod_index_counters_misses_total[5m]))
注意:misses_total 是所有集合的未命中总和,不是按索引维度,所以分母需对齐聚合层级。
为什么不能只看 db.stats() 或 serverStatus 里的索引数据
db.stats() 返回 "indexCount" 和 "indexSize",只是静态大小信息,不反映使用频率;db.serverStatus().indexCounters 在较新版本(4.4+)已被移除 —— 官方明确弃用,因为 WiredTiger 不再维护全局索引计数器。
所以:
-
serverStatus.indexCounters在 4.4+ 版本返回空或报错,别再依赖 -
db.stats()的"indexCount"是当前索引数量,和“命中”完全无关 - 真要监控命中行为,必须用 Exporter +
indexusage,或手动结合explain+ 日志分析
最容易被忽略的是:索引命中率本身是个“派生指标”,MongoDB 不直接暴露它;你得自己拼凑访问量与未命中量,而且不同采集方式(mongostat vs Exporter)口径完全不同,混用会导致误判。


















