MongoDB集合未使用唯一索引执行扫描问题咨询
为什么MongoDB没有使用你的name字段唯一索引?
我来帮你拆解下问题所在,主要是两个关键因素,其中第一个是核心原因:
1. 查询与索引的Collation配置不匹配
你的索引明确配置了自定义的collation规则:
"collation" : { "locale" : "en", "caseLevel" : false, "caseFirst" : "off", "strength" : 2, "numericOrdering" : false, "alternate" : "non-ignorable", "maxVariable" : "punct", "normalization" : false, "backwards" : false, "version" : "57.1" }
而你执行find({name: 'B'})时没有指定对应的collation,MongoDB会默认使用集合或全局的collation规则来处理查询。MongoDB的规则是:只有当查询的collation和索引的collation完全一致时,才能使用该索引。两者不匹配的情况下,查询优化器无法利用这个索引,只能退而求之走全集合扫描(COLLSCAN)。
解决办法:
在查询时显式指定和索引完全一致的collation,示例代码如下:
db.xxx.find({name: 'B'}).collation({ "locale" : "en", "caseLevel" : false, "caseFirst" : "off", "strength" : 2, "numericOrdering" : false, "alternate" : "non-ignorable", "maxVariable" : "punct", "normalization" : false, "backwards" : false, "version" : "57.1" }).explain('executionStats')
执行这个查询后,你应该就能看到执行计划切换为索引扫描(IXSCAN)了。
2. Sparse索引的潜在影响(次要因素)
你的索引设置了sparse: true,这意味着只有包含name字段且字段值不为null的文档才会被纳入索引。如果你的集合中大部分文档都没有name字段,查询优化器可能会认为全集合扫描比遍历索引更高效,但从你的执行结果来看,nReturned:1且总文档数是26,说明至少有一个文档存在name:'B',这种情况下sparse索引通常还是会被优先选择,所以这个不是核心问题。
你可以用下面的命令确认集合中包含有效name字段的文档数量:
db.xxx.countDocuments({name: {$exists: true, $ne: null}})
内容的提问来源于stack exchange,提问作者lone_worrior
相关产品推荐
相关产品推荐

