Задать вопрос
@zuart
... уже и не знаю, нуп, похоже ...

Почему выборка с поиском по вложенному полю с обратной сортировкой тормозит?

Приветствую.

Есть относительно небольшая база в 2.5млн документов. Структура документов не сильно важна, тем более она "динамическая". Но есть запрос, который выполняется регулярно и довольно часто - выборка "самого-самого" и по условию отсутствия вложенного поля:
db.getCollection('special').find({
    'checker.updated': { '$exists': false }
}).sort({'postedNum':-1}).limit(1)


Так вот дело в том, что этот запрос на базе выполняется около 40сек... Тогда как такой:
db.getCollection('special').find({
    'checker.updated': { '$exists': false }
}).sort({'postedNum':1}).limit(1)


выплевывает результат менее чем за одну.

Пробовал индексами химичить:
- раздельно на поля postedNum:-1 и checker.updated:1
- делал сдвоенные postedNum:-1 + checker.updated:1
- пробовал использовать индекс на весь checker

Результата ноль. Если сортировать по возрастанию - моментально, как только реверс на убывание - "куримбамбук". Даже появились мысли, не свалить ли на что-то реляционное скульное, но там останавливает скорость активной работы с таблицами размером более 20-25млн записей...

Update 1. Попробовал заменить фильтр с вложенного поля на простое (создал копию из 'checker.updated' => 'checkerUpdated') - тоже все стало "летать" и с прямой и с обратной сортировкой. Ничего не понимаю... Как вариант решения, конечно, отказаться полностью от "вложенной структуры", но блин, это перелопатить половину кода и накостылять кучу блоков, которые должны будут "сворачивать/разворачивать" рабочие структуры в одноуровневые списки полей

Update 2. А теперь вообще ничего не понимаю. Повырубал все процессы/ноды, которые выполняли в параллели один и тот же запрос с вот этой "обратной сортировкой" (условия оставил, сортировку убрал - что не есть хорошо, но как временный вариант подойдет), и тут же ушли дикие задержки на выполнение этого же самого запроса с 40с+ до 2с... Получается, что такие дикие задержки дает множество параллельных обращений к базе с одним и тем же запросом, но именно в сочетании "сортировка + фильтр по вложенному полю"... Что за фигня???
  • Вопрос задан
  • 267 просмотров
Подписаться 2 Сложный Комментировать
Решения вопроса 1
zoonman
@zoonman
⋆⋆⋆⋆⋆
Для начала неплохо было бы взглянуть на вывод explain.
Производительность приложения напрямую зависит от используемого индекса, но в данном случае вы используете $exists: false, что автоматически приводит к ситуации полного сканирования коллекции.
Индексирование такого поля не выход. Если вы хотите индексировать, то в индекс должно попадать значение.
Чтобы решить проблему, вам необходимо при вставке добавлять нечто вроде updated: false.
Если вы храните там дату, то используйте дополнительное поле updatedAt. Не следует смешивать разные типы данных в одном поле - монга может не построить индекс.
Для обратной сортировки вы можете создать дополнительный индекс с обратным порядком.
Подробнее о сортировках можно прочесть здесь https://docs.mongodb.com/manual/tutorial/sort-resu...
Вы можете построить совмещенный индес с прямым проходом по свойству и обратной сортировкой, только следует соблюдать порядок.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@caballero
Программист
потому что модные до недавнего времени nosql базы данных не предназначены для сложных и одновременно быстрых выборок.
Это не последняя ваша проблема - чем раньше перейдете на нормальную реляционную БД тем меньше проблем в будущем.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы