MongoDB覆盖的查询无法满足Index的查询

时间:2018-01-20 01:16:59

标签: mongodb

以下是我的环境详情: 我从here获得了示例MongoDB集合或数据库。它创造了一个餐厅系列。一份文件如下:

{
"_id" : ObjectId("5a6292fd6b741ed385c94524"),
"address" : {
    "building" : "97-22",
    "coord" : [ 
        -73.8601152, 
        40.7311739
    ],
    "street" : "63 Road",
    "zipcode" : "11374"
},
"borough" : "Queens",
"cuisine" : "Jewish/Kosher",
"grades" : [ 
    {
        "date" : ISODate("2014-11-24T00:00:00.000Z"),
        "grade" : "Z",
        "score" : 20
    }, 
    {
        "date" : ISODate("2013-01-17T00:00:00.000Z"),
        "grade" : "A",
        "score" : 13
    }, 
    {
        "date" : ISODate("2012-08-02T00:00:00.000Z"),
        "grade" : "A",
        "score" : 13
    }, 
    {
        "date" : ISODate("2011-12-15T00:00:00.000Z"),
        "grade" : "B",
        "score" : 25
    }
],
"name" : "Tov Kosher Kitchen",
"restaurant_id" : "40356068"

}

我创建了两个索引,如:

db.restaurants.createIndex({"restaurant_id" : 1}, {"name" : "restaurantsid"})
db.restaurants.createIndex({"address.zipcode" : 1}, {"name" : "zipcode"})

索引如下:

> db.restaurants.getIndexes()
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.restaurants"
    },
    {
        "v" : 2,
        "key" : {
            "address.zipcode" : 1
        },
        "name" : "zipcode",
        "ns" : "test.restaurants"
    },
    {
        "v" : 2,
        "key" : {
            "restaurant_id" : 1
        },
        "name" : "restaurantsid",
        "ns" : "test.restaurants"
    }
]

我想在这里实现的是我在下面的查询中需要完整的restaurant_id或者zipCodes列表。我知道有一个索引存在于记忆中。我写了一个这样的查询:

db.restaurants.find({}, {"address.zipcode" : 1, "_id" : 0}).explain()

结果是:

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.restaurants",
        "indexFilterSet" : false,
        "parsedQuery" : {

        },
        "winningPlan" : {
            "stage" : "PROJECTION",
            "transformBy" : {
                "address.zipcode" : 1,
                "_id" : 0
            },
            "inputStage" : {
                "stage" : "COLLSCAN",
                "direction" : "forward"
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "714fc0d524cf",
        "port" : 27017,
        "version" : "3.6.0",
        "gitVersion" : "a57d8e71e6998a2d0afde7edc11bd23e5661c915"
    },
    "ok" : 1
}

它总是给我" stage" :" COLLSCAN"。

所以现在让我们得到所有的对象id。 MongoDB在ObjectId上创建了一个默认索引。

db.restaurants.find({}, {"_id" : 1}).explain()

结果是:

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.restaurants",
        "indexFilterSet" : false,
        "parsedQuery" : {

        },
        "winningPlan" : {
            "stage" : "PROJECTION",
            "transformBy" : {
                "_id" : 1
            },
            "inputStage" : {
                "stage" : "COLLSCAN",
                "direction" : "forward"
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "714fc0d524cf",
        "port" : 27017,
        "version" : "3.6.0",
        "gitVersion" : "a57d8e71e6998a2d0afde7edc11bd23e5661c915"
    },
    "ok" : 1
}

奇怪的是MongoDB没有达到索引,但我需要的所有数据都存在于索引中。为什么获奖计划是" COLLSCAN"总是?

与restaurantsid指数相同。也许我错过了什么。 在编写查询时我也照顾"_id" : 0

每次都必须使用hint()来使用这样的索引:

> db.restaurants.explain("executionStats").find({}, {"address.zipcode" : 1, "_id" : 0}).hint("zipcode")
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.restaurants",
        "indexFilterSet" : false,
        "parsedQuery" : {

        },
        "winningPlan" : {
            "stage" : "PROJECTION",
            "transformBy" : {
                "address.zipcode" : 1,
                "_id" : 0
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "address.zipcode" : 1
                },
                "indexName" : "zipcode",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "address.zipcode" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "address.zipcode" : [
                        "[MinKey, MaxKey]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "executionStats" : {
        "executionSuccess" : true,
        "nReturned" : 25359,
        "executionTimeMillis" : 79,
        "totalKeysExamined" : 25359,
        "totalDocsExamined" : 0,
        "executionStages" : {
            "stage" : "PROJECTION",
            "nReturned" : 25359,
            "executionTimeMillisEstimate" : 63,
            "works" : 25360,
            "advanced" : 25359,
            "needTime" : 0,
            "needYield" : 0,
            "saveState" : 199,
            "restoreState" : 199,
            "isEOF" : 1,
            "invalidates" : 0,
            "transformBy" : {
                "address.zipcode" : 1,
                "_id" : 0
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "nReturned" : 25359,
                "executionTimeMillisEstimate" : 43,
                "works" : 25360,
                "advanced" : 25359,
                "needTime" : 0,
                "needYield" : 0,
                "saveState" : 199,
                "restoreState" : 199,
                "isEOF" : 1,
                "invalidates" : 0,
                "keyPattern" : {
                    "address.zipcode" : 1
                },
                "indexName" : "zipcode",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "address.zipcode" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "address.zipcode" : [
                        "[MinKey, MaxKey]"
                    ]
                },
                "keysExamined" : 25359,
                "seeks" : 1,
                "dupsTested" : 0,
                "dupsDropped" : 0,
                "seenInvalidated" : 0
            }
        }
    },
    "serverInfo" : {
        "host" : "714fc0d524cf",
        "port" : 27017,
        "version" : "3.6.0",
        "gitVersion" : "a57d8e71e6998a2d0afde7edc11bd23e5661c915"
    },
    "ok" : 1
}

在命令行使用MongoDB提示很好,但是当有应用程序运行时它们很糟糕,并且它们无法从代码中使用hint()。为什么MongoDB不能在不使用hint()的情况下自行使用正确的索引?

1 个答案:

答案 0 :(得分:1)

好吧,在3.6中为你的特定情况引入了一个新的标志。默认情况下禁用它。

如果您想使用索引

,请设置此标志
mongod --setParameter internalQueryPlannerGenerateCoveredWholeIndexScans=1

更多信息here& here