为什么MongoDB中的覆盖查询有时会变慢?

时间:2014-05-20 07:21:47

标签: mongodb mongodb-query

我的印象是,覆盖的查询总是比扫描集合本身更快。那么为什么这个覆盖的查询更慢?

涵盖查询:

> db.group_panel_responses.find({}, {_id: 0, _panel_id: 1, _group_id: 1, response_count: 1}).hint({_panel_id: 1, _group_id: 1, response_count: -1}).explain()
{
    "cursor" : "BtreeCursor _panel_id_1__group_id_1_response_count_-1",
    "isMultiKey" : false,
    "n" : 20000,
    "nscannedObjects" : 0,
    "nscanned" : 20000,
    "nscannedObjectsAllPlans" : 0,
    "nscannedAllPlans" : 20000,
    "scanAndOrder" : false,
    "indexOnly" : true,
    "nYields" : 156,
    "nChunkSkips" : 0,
    "millis" : 44,
    "indexBounds" : {
        "_panel_id" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ],
        "_group_id" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ],
        "response_count" : [
            [
                {
                    "$maxElement" : 1
                },
                {
                    "$minElement" : 1
                }
            ]
        ]
    },
    "server" : "DAAVID.local:27017",
    "filterSet" : false
}

相同的查询,但没有暗示索引,所以不是一个被覆盖的查询:

> db.group_panel_responses.find({}, {_id: 0, _panel_id: 1, _group_id: 1, response_count: 1}).explain()
{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 20000,
    "nscannedObjects" : 20000,
    "nscanned" : 20000,
    "nscannedObjectsAllPlans" : 20000,
    "nscannedAllPlans" : 20000,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 156,
    "nChunkSkips" : 0,
    "millis" : 40,
    "server" : "DAAVID.local:27017",
    "filterSet" : false
}

1 个答案:

答案 0 :(得分:2)

请记住,索引所涵盖的查询通常比常规查询更快,因为您可以在一个步骤中检索每个文档的字段,而不是常规查询中的两个字段,您可以在其中查找索引找到文档的位置,然后点击集合本身以检索字段。

为了简化一点,在我的选择标准将检索20000个文档的正常情况下,正常查询将具有40000次访问(索引为20000,对于集合为20000),而覆盖查询将只有20000次访问。

但是,在您的测试用例中,您没有选择条件。因此,覆盖和未覆盖的两个查询都将执行完整的集合扫描。在这种情况下,您几乎可以通过选择标准丢失覆盖查询的所有性能提升。

如果您真的想测试覆盖查询的值,我会使用更大的文档集合和更具选择性的查询。如果您使用的测试代表您的实际生产用量,我根本不会期望任何性能提升。