跳转到主内容
极星编程网:以代码为星,赴技术山海!

怎么在MongoDB中测试定向查询是否生效_explain("executionStats")分析路由状态

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

相关文章