mongodb在排序时不使用索引?

时间:2011-12-09 03:27:51

标签: mongodb mongodb-indexes nosql

我有一个包含这些索引的集合:

> db.message.getIndexKeys()
[
    {
        "_id" : 1
    },
    {
        "msgid" : 1
    },
    {
        "keywords" : 1,
        "msgid" : 1
    }
]

和像

这样的查询
db.message.find({'keywords': {'$all': ['apple', 'banana']}}).limit(30).explain()

与索引

一起正常工作
{
    "cursor" : "BtreeCursor keywords_1_msgid_1",    
    "nscanned" : 96,
    "nscannedObjects" : 96,
    ...
}

但使用msgid进行排序时:

db.message.find({'keywords': {'$all': ['apple', 'banana']}})
    .sort({msgid:-1})
    .limit(30).explain()

mongodb不再使用索引:

{
"cursor" : "BtreeCursor msgid_1 reverse",
"nscanned" : 1784455,
"nscannedObjects" : 1784455,
...
}

任何解决方案?

2 个答案:

答案 0 :(得分:32)

Mongo实际上使用索引(您可以通过在解释中看到BtreeCursor来判断),而不是复合索引。

重要的是要记住,当你有一个复合指数时,方向很重要。

尝试:db.ensureIndex({ keywords: 1, msg_id: -1 })

Mongo选择在您的示例中反向使用msg_id索引,因为它以更快的顺序检索结果,然后在O(n)时间内匹配,而不是匹配结果,然后在O(nlogn)时间内排序。

答案 1 :(得分:1)

正在使用索引 - msgid上的索引。 MongoDB通过尝试所有可能的索引并使用先完成的任何索引来选择用于查询的索引。此结果将缓存1,000个查询,或者直到对集合进行一定数量的修改(数据更改,新索引等)。

您可以通过将true传递给explain()来查看所有尝试的查询计划。

有关详细信息,请参阅http://www.mongodb.org/display/DOCS/Query+Optimizer