MongoDB:为什么不按多个键排序使用索引?

时间:2012-08-22 11:55:31

标签: mongodb indexing mongodb-indexes

问题: 我有一个非常大的集合,由字段ts索引:(时间戳)

> db.events.ensureIndex({'ts': -1})

我想获得最后5个条目。让我感到惊讶的是,查询不使用索引,因此非常慢:

> db.events.find().sort({'ts': -1, '_id': -1}).limit(5)

但是,仅按ts或其他字段排序会使用索引:

> db.events.find().sort({'ts': -1}).limit(5)
> db.events.find().sort({'_id': -1}).limit(5)

这是MongoDB中的一个错误,这确实是一个记录在案的功能还是我做错了什么?

其他信息:

> db.events.find().sort({'ts': -1, '_id': -1}).limit(5).explain()
{
    "cursor" : "BasicCursor",
    "nscanned" : 795609,
    "nscannedObjects" : 795609,
    "n" : 5,
    "scanAndOrder" : true,
    "millis" : 22866,
    "nYields" : 73,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {

    }
}
> db.events.find().sort({'ts': -1}).limit(5).explain()
{
    "cursor" : "BtreeCursor ts_-1",
    "nscanned" : 5,
    "nscannedObjects" : 5,
    "n" : 5,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {
            "ts" : [
                    [
                            {
                                    "$maxElement" : 1
                            },
                            {
                                    "$minElement" : 1
                            }
                    ]
            ]
    }
}

1 个答案:

答案 0 :(得分:5)

值得阅读索引建议的Indexing Strategies部分&常见问题维基页面。

您可能会遗漏一些注意事项:

  • MongoDB每个查询只使用一个索引

  • 使用的sort列必须是索引中的最后一列

因此,对于您的示例,您应该在ts_id上添加复合索引:

  

db.events.ensureIndex({'ts': - 1,'_ id': - 1});

..并与explain()确认排序现在正在使用预期的索引:

> db.events.find().sort({'ts': -1, '_id':-1}).limit(5).explain()
{
    "cursor" : "BtreeCursor ts_-1__id_-1",
    "nscanned" : 5,
    "nscannedObjects" : 5,
    "n" : 5,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {
        "ts" : [
            [
                {
                    "$maxElement" : 1
                },
                {
                    "$minElement" : 1
                }
            ]
        ],
        "_id" : [
            [
                {
                    "$maxElement" : 1
                },
                {
                    "$minElement" : 1
                }
            ]
        ]
    }
}