MongoDB медленные запросы как найти и оптимизировать
Рейтинг: 70.3% · 30 голосов
Войдите, чтобы голосовать
Голосовать «За» и «Против» могут только авторизованные пользователи. Войдите в свой аккаунт — или зарегистрируйтесь, это займёт минуту.
Нет аккаунта? Зарегистрироваться
✔ Лучший ответ выбран автором и совпадает с автоматическим подбором — k8s2000
Подробно про индексную стратегию для вашего случая: правило ESR (Equality, Sort, Range) — сначала поля по которым делаешь точное равенство (userId =), потом поля сортировки (createdAt), потом поля диапазонов. Для запросов вида find({userId: X, createdAt: {$gte: Y}}).sort({createdAt: -1}) оптимальный индекс {userId: 1, createdAt: -1}. Также проверь через db.events.stats() и…
Re: MongoDB медленные запросы как найти и оптимизировать
Первым делом включи профилировщик MongoDB: db.setProfilingLevel(1, { slowms: 100 }) — это запишет в system.profile все запросы медленнее 100мс. Потом смотри db.system.profile.find().sort({millis:-1}).limit(10) — найдёшь самых злодеев. Ищи поле docsExamined: если оно в разы больше nReturned — индекс либо отсутствует, либо неэффективен.
Re: MongoDB медленные запросы как найти и оптимизировать
На 80 млн документов составной индекс обязателен. Создай db.events.createIndex({userId: 1, createdAt: -1}) — порядок полей важен. Если запросы всегда фильтруют по userId и сортируют по createdAt desc — именно такой индекс покроет оба условия и избежит in-memory sort.
Re: MongoDB медленные запросы как найти и оптимизировать
explain() твой лучший друг. db.events.find({userId: 'xxx'}).sort({createdAt: -1}).explain('executionStats') покажет: используется ли индекс (IXSCAN vs COLLSCAN), сколько документов просканировано, есть ли этап SORT в памяти. Если видишь totalDocsExamined >> nReturned или стадию SORT — есть что оптимизировать.
Re: MongoDB медленные запросы как найти и оптимизировать
✔ Лучший ответ — выбран автором и совпадает с авто-подбором
Подробно про индексную стратегию для вашего случая: правило ESR (Equality, Sort, Range) — сначала поля по которым делаешь точное равенство (userId =), потом поля сортировки (createdAt), потом поля диапазонов. Для запросов вида find({userId: X, createdAt: {$gte: Y}}).sort({createdAt: -1}) оптимальный индекс {userId: 1, createdAt: -1}. Также проверь через db.events.stats() и db.events.totalIndexSize() — если индексы не влезают в RAM (wiredTiger кэшируется через parameter storage.wiredTiger.engineConfig.cacheSizeGB, по умолчанию 50% RAM), то производительность деградирует из-за постоянных page fault. Ещё: если поле createdAt типа string а не Date — сортировка будет лексикографической и индекс не поможет как ожидается. Всегда храни даты как Date.
Re: MongoDB медленные запросы как найти и оптимизировать
К сказанному добавлю две вещи, о которых обычно вспоминают поздно. Первое: на 80 млн документов само построение индекса нагрузит прод — в 6.0 билды уже не блокирующие, но IO жрут прилично, запускай в окно минимальной нагрузки, а на реплика-сете лучше rolling build по нодам. Второе: проверь, влезают ли индексы в WiredTiger cache (по умолчанию ~50% RAM) — сравни db.events.totalIndexSize() с размером кэша. Если индексы не помещаются в память, никакой IXSCAN не спасёт, будешь читать индекс с диска. И если старые события не нужны — TTL-индекс по createdAt, коллекция хотя бы перестанет пухнуть.
Re: MongoDB медленные запросы как найти и оптимизировать
@k8spro, дополню по explain: кроме executionStats стоит смотреть allPlansExecution — бывает, что планер выбирает не тот индекс из нескольких похожих, и запрос тормозит при формально существующем правильном индексе. У нас так было с {userId:1, createdAt:-1} и старым {userId:1, status:1}: планер закэшировал план под второй, и до чистки через db.events.getPlanCache().clear() запросы упорно шли мимо нужного индекса.
- juniorredteam
- Сообщения: 66
- Зарегистрирован: 11 май 2026, 07:16
Re: MongoDB медленные запросы как найти и оптимизировать
@Sjobs, смотря какой паттерн запросов. Если основной кейс — «покажи последние события юзера» для UI, Mongo с индексом {userId, createdAt} отрабатывает за миллисекунды, и тащить ClickHouse ради этого — лишняя сущность в проде плюс второй пайплайн доставки данных. ClickHouse оправдан, когда пошла настоящая аналитика: агрегации за месяцы по всем юзерам сразу. Я бы сначала починил индексы, а уже потом, если останутся тяжёлые аналитические запросы, выносил их отдельно — не наоборот.
Поделиться темой:
✈ Telegram
VK
- Похожие темы
-
-
- Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
8 ответов · 79 просмотров
-
- GCP Billing неожиданный счёт за Cloud Storage как разобраться и оптимизировать расходы
8 ответов · 79 просмотров
-
- PostgreSQL 17 — партиционирование по диапазону дат, реально ли ускорить запросы в 10 раз?
5 ответов · 72 просмотров
-
-
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость