Pergunta

Question: I have a very large collection that is indexed by field ts: (timestamp)

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

I want to get last 5 entries. What surprises me is that the query doesn't use the index and is thus very slow:

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

However, sorting just by ts or the other field uses index as it should:

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

Is this a bug in MongoDB, is this indeed a documented feature or am I doing something wrong?

Additional info:

> 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
                            }
                    ]
            ]
    }
}
Foi útil?

Solução

It's worth having a read of the Indexing Strategies section of the Indexing Advice & FAQ wiki page.

There are a few considerations that you may be missing:

  • MongoDB only uses one index per query

  • the sort column used must be the last column in the index

So, for your example you should add a compound index on ts and _id:

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

.. and confirm with explain() that the sort is now using the expected index:

> 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
                }
            ]
        ]
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top