Я пытаюсь сделать составной индекс для многоключевого поля быстродействующим при сортировке, но я не могу понять это. используя mon go 3.6 с wiredtiger здесь. мои документы выглядят так (удалили все, что не запрашивается и не находится в индексе):
{
_id: ObjectId(),
something: {
nested: [{_id: ObjectId()}, {_id: ObjectId()}, {_id: ObjectId()}]
},
another: {
thing: {
_id: ObjectId()
}
}
}
в коллекции несколько миллионов документов, и у меня есть следующие индексы:
{ "_id": 1 }
{ "something.nested._id": 1, "another.thing._id": 1, "_id": -1 }
{ "something.nested._id": 1, "_id": -1, "another.thing._id": 1 }
{ "_id": -1, "something.nested._id": 1, "another.thing._id": 1 } # this one only exists in a non-production system with far less documents
я пытаюсь выполнить запрос, подобный этому (идеальный случай):
db.getCollection('whatever').find({"something.nested._id": ObjectId("5b88937a98162d5595b00000"), "another.thing._id": {"$ne": ObjectId("5b88937a98162d5595b00000")}} ).sort(_id: -1).limit(51)
объяснение говорит мне, что он выполняет обратную IXSCAN
в индексе _id
, затем FETCH
с фильтром на "something.nested._id"
и "another.thing._id"
. это приводит к тому, что многие документы сканируются, прежде чем он найдет достаточно для удовлетворения предела. он не использует ни один из индексов, которые содержат "something.nested._id"
. в промежуточной системе я пробовал составной индекс, у которого в качестве префикса _id
(я где-то читал), но это не оптимальный выбор для планировщика, и если я его форсирую, у меня будет похожий результат.
единственное, что каким-либо образом улучшает этот запрос, - это избавиться от .sort({_id: -1})
(тогда это на самом деле очень быстро), но естественная сортировка может быть неправильной, поэтому я не могу использовать это (хотя в во всех моих тестах это оказалось правильным).
так есть ли эффективный индекс, который я просто пропускаю, или мы загнали себя в угол с нашей моделью данных?