判断MongoDB索引是否生效,核心看executionStats.nReturned与totalDocsExamined比值:接近则未走索引,远小于则索引用但效果差,相等且值小为理想;再查stage是否为IXSCAN而非COLLSCAN。

要判断MongoDB查询是否走索引、为什么慢、该建什么索引,必须直接查看explain输出中的stage字段——IXSCAN代表命中索引高效定位,COLLSCAN代表全集合扫描,数据量稍大就会严重拖慢响应。
获取带执行统计的explain结果
在mongo shell中对目标查询调用.explain("executionStats"),例如:db.orders.explain("executionStats").find({status: "shipped", createdAt: {$gt: ISODate("2026-01-01")}})。
必须指定"executionStats"模式,否则看不到totalDocsExamined和executionTimeMillis等关键性能数字。
这一步不能省略为.explain()或.explain("queryPlanner"),否则你只能看到“计划可能怎么走”,而看不到“实际走了多少文档”。
识别IXSCAN与COLLSCAN所在层级
在返回结果中定位explain.executionStats.executionStages对象,它是一个嵌套结构,最外层stage是根节点,其inputStage(或inputStages)是子节点。
从叶子节点开始向上看:所有stage: "IXSCAN"都出现在inputStage里,说明索引扫描是数据源;而stage: "COLLSCAN"若出现在叶子位置,就表示根本没走任何索引。
【IXSCAN必须配合keyPattern和indexName才有意义】——如果看到IXSCAN但indexName为空或为"_id_",而你的查询条件根本不含_id,那说明这个IXSCAN是误判或被强制跳过,实际仍退化为COLLSCAN。
对比关键指标判断真实开销
方法一:看totalDocsExamined与nReturned比值
若totalDocsExamined远大于nReturned(比如10万 vs 10),基本可断定是COLLSCAN主导;若两者接近(如120 vs 100),且stage路径中存在IXSCAN→FETCH,则说明索引有效命中。
方法二:盯住executionStages.stage链的最后一级
如果最终stage是FETCH,且它的inputStage.stage是IXSCAN,说明先查索引再取文档,属正常路径;
如果最终stage直接是COLLSCAN,或IXSCAN下面还套了一层COLLSCAN(极少见,多因索引不覆盖+排序强制内存扫描),那就必须优化。
方法三:检查allPlansExecution模式下的备选计划
运行.explain("allPlansExecution"),对比winningPlan和其他candidatePlan的executionStats.totalDocsExamined。如果获胜计划和落选计划数值相差无几,说明优化器没找到真正高效的索引路径,当前索引设计失效。
快速验证索引是否生效
第一步:确认查询条件字段已建索引
执行db.orders.getIndexes(),查找key包含status和createdAt的条目。没有就立刻建:db.orders.createIndex({status: 1, createdAt: -1})。
第二步:清除计划缓存避免干扰
运行db.orders.dropIndex({status: 1, createdAt: -1})再重建,或直接执行db.runCommand({clearQueryCache: "orders"})(MongoDB 5.0+)。
第三步:重跑explain,观察winningPlan.inputStage.stage是否变为IXSCAN,且totalDocsExamined大幅下降。


















