MongoDB Distinct 有时使用索引,有时不使用索引



我有集合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上使用索引,我可以做一些事情来强制使用索引吗?

笔记:

  1. 集合B比集合A大很多,distinct可以使用的索引大小有限制吗?
  2. 我已经阅读:在mongoDB和MongoDB中计算不同的值 - 查询的不同不使用索引,它们无助于解释我所看到的行为差异。
  3. 两个系列都sharded
  4. 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()只能对根字段使用索引,而不能对数组或子文档使用索引。

最新更新