2

我有以下嵌入式二级复合索引:

db.people.ensureIndex({"sources_names.source_id":1,"sources_names.value":1})

这是 db.people.getIndexes() 的一部分:

{
    "v" : 1,
    "key" : {
        "sources_names.source_id" : 1,
        "sources_names.value" : 1
    },
    "ns" : "diglibtest.people",
    "name" : "sources_names.source_id_1_sources_names.value_1"
}

所以我运行以下索引覆盖查询:

db.people.find({ "sources_names.source_id": ObjectId('5166d57f7a8f348676000001'), "sources_names.value": "Ulrike Weiland" }, {"sources_names.source_id":1, "sources_names.value":1, "_id":0} ).pretty()
{
    "sources_names" : [
        {
            "value" : "Ulrike Weiland",
            "source_id" : ObjectId("5166d57f7a8f348676000001")
        }
    ]
}

花了大约5秒钟。所以我运行解释:

db.people.find({ "sources_names.source_id": ObjectId('5166d57f7a8f348676000001'), "sources_names.value": "Ulrike Weiland" }, {"sources_names.source_id":1, "sources_names.value":1, "_id":0 }).explain()
{
    "cursor" : "BtreeCursor sources_names.source_id_1_sources_names.value_1",
    "isMultiKey" : true,
    "n" : 1,
    "nscannedObjects" : 1260353,
    "nscanned" : 1260353,
    "nscannedObjectsAllPlans" : 1260353,
    "nscannedAllPlans" : 1260353,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 4,
    "nChunkSkips" : 0,
    "millis" : 4308,
    "indexBounds" : {
        "sources_names.source_id" : [
            [
                ObjectId("5166d57f7a8f348676000001"),
                ObjectId("5166d57f7a8f348676000001")
            ]
        ],
        "sources_names.value" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : "dash-pc.local:27017"
}

但是为什么这个索引覆盖查询会遍历整个数据库呢?我应该如何创建索引来提高性能?

谢谢!

4

1 回答 1

0

您正在多个地方使用多键索引(即sources_names.source_id),来自文档(http://docs.mongodb.org/manual/tutorial/create-indexes-to-support-queries/#create-indexes-that-support-覆盖查询):

在以下情况下,索引不能覆盖查询:

集合中任何文档中的任何索引字段都包含一个数组。如果索引字段是数组,则索引成为多键索引索引,不能支持覆盖查询。

您可以从解释中看出这是一个多键索引:

"isMultiKey" : true,

基本上,点表示法被归类为多键,因为sources_names它是一个数组,因此索引包含一个数组。

至于提高速度:我没有看过这个,但你的问题在这里:

"sources_names.value" : [
    [
        {
            "$minElement" : 1
        },
        {
            "$maxElement" : 1
        }
    ]
]

因此,该索引没有被最佳地用于查找sources_names.value.

编辑

我觉得我刚才给出的答案有点奇怪,因为这不应该是一个多键索引,所以我实际上去测试了这个:

> db.gh.ensureIndex({'d.id':1,'d.g':1})
> db.gh.find({'d.id':5, 'd.g':'d'})
{ "_id" : ObjectId("516826e5f44947064473a00a"), "d" : { "id" : 5, "g" : "d" } }
> db.gh.find({'d.id':5, 'd.g':'d'}).explain()
{
        "cursor" : "BtreeCursor d.id_1_d.g_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "d.id" : [
                        [
                                5,
                                5
                        ]
                ],
                "d.g" : [
                        [
                                "d",
                                "d"
                        ]
                ]
        },
        "server" : "ubuntu:27017"
}

看来我最初的想法是正确的,这不应该是多键索引。value我认为你有一些脏数据,这给你带来了问题。

我会检查您的数据库并确保您的记录输入正确。

你很可能有类似的东西:

{
    "sources_names" : [
        {
            "value" : ["Ulrike Weiland", 1],
            "source_id" : ObjectId("5166d57f7a8f348676000001")
        }
    ]
}

某处。

于 2013-04-12T15:03:04.690 回答