Проблемът е, че нито един от вашите индекси всъщност не помага при сортираната заявка. Това е причината за големия брой сканирани обекти и наличието на SORT_KEY_GENERATOR
етап (сортиране в паметта, ограничено до 32MB).
Несортираната заявка, от друга страна, може да използва или { category: 1, _id: 1 }
или { category: 1, _id: 1, sticky: 1, lastPostAt: 1 }
индекси. Обърнете внимание, че е напълно валидно да използвате и едното, и другото, тъй като едното съдържа префикса на другия. Вижте Префикси за повече подробности.
MongoDB find()
queries обикновено използва само един индекс, така че един съставен индекс трябва да обслужва всички параметри на вашата заявка. Това ще включва и двата параметра на find()
и sort()
.
Добър текст за това как трябва да бъде създаден вашият индекс е наличен в Оптимизиране на съставни индекси на MongoDB. Да вземем основната точка на статията, където подреждането на съставния индекс трябва да бъде равенство --> сортиране --> диапазон :
Вашата заявка "форма" е:
db.collection.find({category:..., _id: {$gt:...}})
.sort({sticky:-1, lastPostAt:-1, _id:1})
.limit(25)
Виждаме това:
category:...
еравенствоsticky:-1, lastPostAt:-1, _id:1
есорт_id: {$gt:...}
е диапазон
И така, съставният индекс, от който се нуждаете, е:
{category:1, sticky:-1, lastPostAt:-1, _id:1}
Където печелившият план на explain()
изходът на вашата заявка с горния индекс показва:
"winningPlan": {
"stage": "LIMIT",
"limitAmount": 25,
"inputStage": {
"stage": "FETCH",
"inputStage": {
"stage": "IXSCAN",
"keyPattern": {
"category": 1,
"sticky": -1,
"lastPostAt": -1,
"_id": 1
},
"indexName": "category_1_sticky_-1_lastPostAt_-1__id_1",
"isMultiKey": false,
"multiKeyPaths": {
"category": [ ],
"sticky": [ ],
"lastPostAt": [ ],
"_id": [ ]
},
"isUnique": false,
"isSparse": false,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"category": [
"[ObjectId('5a779b31f4fa724121265142'), ObjectId('5a779b31f4fa724121265142')]"
],
"sticky": [
"[MaxKey, MinKey]"
],
"lastPostAt": [
"[MaxKey, MinKey]"
],
"_id": [
"(ObjectId('5a779b5cf4fa724121269be8'), ObjectId('ffffffffffffffffffffffff')]"
]
}
}
}
}
Имайте предвид, че печелившият план не съдържа SORT_KEY_GENERATOR
сцена. Това означава, че индексът може да се използва напълно за отговор на сортираната заявка.