我有集合A
,在"field1
"上有一个非唯一的索引。
如果我运行:
db.A.explain().distinct("field1")
我得到:
"winningPlan" : {
"stage" : "PROJECTION",
...
"inputStage" : {
"stage" : "DISTINCT_SCAN",
"keyPattern" : {
"field1" : 1.0
},
...
}
这表明它将使用索引进行非重复调用。
但是,在"type2.key
"上具有非唯一索引的集合B
中,如果我运行:
db.B.explain().distinct("type2.key")
我得到:
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"$and" : []
},
...
}
这似乎意味着它不使用索引。
为什么distinct
可以在收集A
上使用索引,而不能在收集B
上使用索引,我可以做一些事情来强制使用索引吗?
笔记:
- 集合
B
比集合A
大很多,distinct
可以使用的索引大小有限制吗? - 我已经阅读:在mongoDB和MongoDB中计算不同的值 - 查询的不同不使用索引,它们无助于解释我所看到的行为差异。
- 两个系列都
sharded
- MongoDB版本是3.2.12
示例文档
{
"_id" : ObjectId("57d6c1cf691fa014e0615aa7"),
"type1" : [
{
"key" : "key1",
"field" : "value1",
},
{
"key" : "key2",
"field" : "value2",
}
],
"type2" : [
{
"key" : "key3",
"field" : "value3",
},
{
"key" : "key4",
"field" : "value4",
}
]
}
该指数处于type2.key
可以使用不同索引的规则是有 https://github.com/mongodb/mongo/blob/v3.4/src/mongo/db/query/get_executor.cpp#L1104
对于这种特殊情况,最重要的一行 https://github.com/mongodb/mongo/blob/v3.4/src/mongo/db/query/get_executor.cpp#L1139 说:
如果我们投影在虚线字段上,请跳过多键索引。
"obj.field2"
是一个虚线字段,因此索引不适用。
所以基本上,distinct()
只能对根字段使用索引,而不能对数组或子文档使用索引。