用explain("executionStats")需重点检查"executionStages"中stage是否为"IXSCAN"且indexName匹配预期,若为"COLLSCAN"则未走索引;分片集群下须逐个验证"shards"数组内各分片的执行阶段与nReturned,避免广播查询;性能隐患看totalDocsExamined与totalKeysExamined比值、works值及各分片executionTimeMillis差异。
怎么用
看查询是否走对了索引
直接在 shell 或驱动里加
,不是看有没有
,而是盯住
里的
和
。如果
是
且
匹配你预期的索引,说明索引生效;要是看到
,就是全表扫了——哪怕数据量小、响应快,也得改。
聚合管道里必须对
阶段单独
,整个 pipeline 的
可能掩盖真实执行路径
模式会真实执行一次查询(带计时),别在生产高峰期对大集合乱跑
分片集群下,
返回的
字段里每个分片都要检查,不能只看一个
分片键没被查询时,
里怎么识别路由失败
重点看
数组长度和每个分片的
。如果所有分片都返回结果,或只有部分分片有数据但
,说明 mongos 没能精准路由,退化成广播查询。这时
通常明显偏高,且
里可能有多个
尝试。
检查查询条件是否包含分片键(或前缀),不带分片键的
/
默认广播到所有 shard
结果中若出现
阶段,基本等于确认广播了
复合分片键如
,只查
不触发路由,必须带
才行
里哪些字段暴露性能隐患
别只盯着
。真正要扣的是
和
的比值:如果前者远大于后者,说明索引过滤效率低(比如用了非前缀匹配);如果两者都很大但
很小,大概率是索引选错或查询条件没利用好索引顺序。
过高(远超
)往往意味着大量文档被跳过,可能是索引不覆盖或排序未命中索引
分片环境下,各
的
差异超过 3 倍,提示数据分布倾斜或某分片负载异常
为 0 但
很大?说明索引扫描范围过大,该加更精确的查询条件或调整索引字段顺序
为什么
有时不显示
常见于两种情况:一是查询根本没走索引(
),二是用了
、
(非前缀)、
这类无法使用普通 B-tree 索引的操作,此时即使建了索引,
也不会填
,但
可能显示
或
(取决于是否启用 text index 或 regex 是否能走索引)。
开头带
且索引字段是前缀时,
才会出现;否则 fallback 到
复合索引中,如果查询只用了后半段字段(比如索引
,只查
),
为空,
是
使用
时,每个分支必须各自能走索引,否则整个
表达式降级为全表扫描
分片集群里,单看主分片的
输出毫无意义;路由是否生效,必须逐个核对
数组里每个成员的执行阶段和返回量。
explain("executionStats")explain("executionStats")"executionSuccess": true"executionStages""stage""indexName"stage"IXSCAN"indexName"COLLSCAN"$matchexplainexplainexecutionStatsexplain"shards"explain"shards""executionStats.nReturned"nReturned > 0"executionStats.executionTimeMillis""allPlansExecution"IXSCANfindcountexplain"scatterGather"{ a: 1, b: 1 }{ b: 123 }aexecutionStats"executionTimeMillis""totalDocsExamined""totalKeysExamined"nReturned"executionStages.works"nReturnedshard"executionTimeMillis""nReturned""totalKeysExamined"explain("executionStats")indexNamestage === "COLLSCAN"$text$regex$whereexplainindexNamestage"TEXT""IXSCAN"$regex^indexNameCOLLSCAN{a:1,b:1}{b:1}indexNamestage"COLLSCAN"$or$orexplainshards