为什么这个简单的MongoDB查询有这么多的nYield?

时间:2014-09-02 03:37:44

标签: mongodb

我有一个带有以下索引的测试数据库:

[
    {
            "v" : 1,
            "key" : {
                    "_id" : 1
            },
            "name" : "_id_",
            "ns" : "blogger.users"
    },
    {
            "v" : 1,
            "key" : {
                    "name" : 1,
                    "age" : 1
            },
            "name" : "name_1_age_1",
            "ns" : "blogger.users"
    },
    {
            "v" : 1,
            "key" : {
                    "age" : 1,
                    "name" : 1
            },
            "name" : "age_1_name_1",
            "ns" : "blogger.users"
    }
]

运行以下查询时:

> db.users.find({"age":{"$gte":21,"$lte":30}})
     .sort({"name":1})
     .hint({"name":1,"age":1})
     .explain()

我得到以下结果

{
    "cursor" : "BtreeCursor name_1_age_1",
    "isMultiKey" : false,
    "n" : 83116,
    "nscannedObjects" : 1000000,
    "nscanned" : 1000000,
    "nscannedObjectsAllPlans" : 1000000,
    "nscannedAllPlans" : 1000000,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 7812,
    "nChunkSkips" : 0,
    "millis" : 1926,
    "indexBounds" : {
            "name" : [
                    [
                            {
                                    "$minElement" : 1
                            },
                            {
                                    "$maxElement" : 1
                            }
                    ]
            ],
            "age" : [
                    [
                            {
                                    "$minElement" : 1
                            },
                            {
                                    "$maxElement" : 1
                            }
                    ]
            ]
    },
    "server" : "Johny-PC:27017",
    "filterSet" : false
}

我多次运行此查询,nYield总是高于7k。没有任何其他进程更新,插入或删除数据。当我在没有提示的情况下运行相同的查询时,结果是相同的。

如果我使用其他索引作为提示运行相同的查询,则nYields为1200 +。

没有提示和排序它很快但是nYields:500+并使用另一个索引,正如预期的那样。

那么有没有办法找出为什么这么多的nYield存在,有人可以解释为什么会这样?

修改   一个简单的查找查询也有很多nYields。所以,问题不在于索引。我可能会遗漏一些东西。

1 个答案:

答案 0 :(得分:3)

您强制查询在hint调用时使用错误的索引,因为查询需要先按age过滤,然后按name排序。您告诉MongoDB使用的索引无法有效地用于此目的。

删除hint来电或将其更改为:

db.users.find({"age":{"$gte":21,"$lte":30}})
 .sort({"name":1})
 .hint("age_1_name_1")
 .explain()

查询需要扫描的文档越多(nscannedObjects),它会产生读锁定的次数越多,因为它等待I / O完成以获取文档。因此查询效率越低,nYield就越高。 500+收益率没有任何问题,它只是意味着它是一个返回大量文档的查询(在这种情况下为83k)。