Индексы в MongoDB: создание, типы и лучшие практики
Что такое индексы в MongoDB?
Индекс — это вспомогательная структура данных, которая ускоряет поиск и сортировку в коллекции. Он позволяет выделить поля документа как ключи для запросов. MongoDB автоматически создаёт индекс по полю _id при создании коллекции. Остальные индексы вы добавляете вручную в зависимости от нагрузки и паттернов запросов.
Коротко: индекс уменьшает объём данных, которые нужно просканировать при выполнении запроса. Уникальные индексы предотвращают вставку дубликатов по указанному полю (например, username или email).
Пример: без индекса вы сортируете и фильтруете явно:
db.collectionName.find({age: {$gt: 50}}).sort({date: -1})Если у вас есть индекс по полю date, отсортированный по убыванию, то сортировку не нужно указывать в запросе:
db.collectionName.find({age: {$gt: 50}})Это снижает стоимость выполнения и часто уменьшает потребление памяти и I/O.
Как создать индекс в MongoDB
Создавать индексы удобно из mongo shell, драйвера или инструментов управления. Перед созданием индекса убедитесь, что у вас есть база данных и коллекция.
Синтаксис базовый:
db.collectionName.createIndex({поле: 1})Значение 1 означает сортировку по возрастанию, -1 — по убыванию.
Примеры:
db.userCollection.createIndex({age: -1})db.userCollection.createIndex({age: 1})MongoDB создаёт имя индекса автоматически, если вы его не задаёте. Для читаемости и управления лучше явно указывать имя.
Создание одиночного индекса
Выберите базу и создайте индекс по одному полю. Пример:
use MUO
db.collectionName.createIndex({username: -1})Индекс username будет храниться в порядке убывания; при соответствующих запросах MongoDB сможет использовать этот порядок.
Multikey индекс
Multikey индекс индексирует массивы и вложенные поля внутри документов. Если поле содержит массив значений, MongoDB создаёт индекс по каждому элементу массива.
Пример индексирования вложенного поля height внутри массива user:
db.customers.createIndex({"user.height": 1})Если user — массив объектов, multikey индекс позволяет эффективно искать документы по любому значению height внутри массива.
Составной индекс
Составной (compound) индекс объединяет несколько полей. Порядок полей в индексе важен — он влияет на то, какие запросы индекс сможет покрыть.
db.customer.createIndex({address: 1, products: 1})Чтобы задать собственное имя индекса:
db.customers.createIndex({location: 1, products: 1, weight: -1}, {name: "myCompoundIndex"})Просмотр всех индексов в коллекции
db.collectionName.getIndexes()Команда вернёт список всех индексов и их параметров.
Когда индексы не помогают
- Запросы, которые сканируют большую часть коллекции по неиндексированному полю, всё равно будут медленными.
- Частые обновления полей, задействованных в индексе, увеличивают накладные расходы на запись: индекс нужно обновлять при каждой записи/обновлении/удалении.
- Если у вас маленькая коллекция, индексирование может не дать выигрыша и только добавит сложность.
Важно оценивать соотношение чтений и записей: при очень высоком числе записей добавление индекса может ухудшить общую производительность.
Альтернативные и смежные подходы
- Денормализация: дублируйте часто запрашиваемые поля в отдельных коллекциях для ускорения чтений.
- Использование агрегатных выражений и предрасчётов (materialized views / агрегационные коллекции).
- Полнотекстовый поиск (text index) для поисковых сценариев по строкам.
- TTL-индексы для автоматического удаления устаревших документов.
Ментальные модели и эвристики
- Правило 80/20: индексируйте поля, которые участвуют в 80% тяжёлых запросов.
- Объём индекса часто меньше, чем объём всей коллекции; ориентируйтесь на селективность поля (чем уникальнее значения, тем полезнее индекс).
- Для составных индексов порядок важен: ставьте наиболее селективное поле первым, если запросы фильтруют по нескольким полям.
Практический чек-лист для разработчика и DBA
Разработчик:
- Проанализировать медленные запросы (explain, profiler).
- Предложить индекс с учётом паттернов запросов.
- Тестировать на staging-окружении.
DBA / DevOps:
- Оценить влияние индекса на записи и диск.
- Создавать индекс в часы малого трафика или использовать background/online создание (в зависимости от версии MongoDB).
- Мониторить размер индекса и использование памяти.
Критерии приёмки
- Запросы из списка целевых стали выполняться быстрее при том же объёме данных.
- Нагрузка на CPU и I/O не возросла критически для остальных операций.
- Создание индекса прошло без ошибок и не нарушило целостность данных.
- Тесты интеграции и нагрузки прошли успешно.
Important: всегда прогоняйте explain() для проверяемых запросов, чтобы убедиться, что MongoDB использует ожидаемый индекс.
Мини‑руководство: как добавить индекс без простоя (общие шаги)
- Проанализируйте запросы и выберите кандидата на индекс.
- Создайте индекс на тестовом окружении и прогоните нагрузочные тесты.
- На production создайте индекс в фоне (если поддерживается) или в окне низкой нагрузки.
- Мониторьте метрики: latency, page fault, index size.
- При необходимости откатите (dropIndex) и вернитесь к шагу 1.
Пример создания индекса с именем и в фоне (версия MongoDB должна поддерживать):
db.collection.createIndex({email: 1}, {name: "email_idx", background: true})Таблица команд быстрого доступа
| Действие | Команда |
|---|---|
| Создать индекс | db.collection.createIndex({поле: 1}) |
| Создать составной индекс | db.collection.createIndex({a:1, b:-1}) |
| Посмотреть индексы | db.collection.getIndexes() |
| Удалить индекс | db.collection.dropIndex(“имя_индекса”) |
Частые ошибки и как их избегать
- Создание индекса по полю с низкой селективностью (например, булево поле) — почти всегда бесполезно.
- Не проверять план запроса (explain) после добавления индекса.
- Игнорирование накладных расходов на запись: индексы усложняют каждую операцию записи.
Краткая сводка
Индексы — обязательный инструмент оптимизации MongoDB. Они ускоряют выборки и сортировки, позволяют реализовать уникальные ограничения и гибко работать с вложенными структурами через multikey. Подходите к созданию индексов осознанно: анализируйте запросы, тестируйте на копиях данных и мониторьте влияние на запись и хранилище.
Summary:
- Выбирайте индексы по реальным нагрузкам.
- Порядок полей в составном индексе важен.
- Тестируйте и мониторьте до и после создания.
Notes: при добавлении индекса на production учитывайте версию MongoDB и возможности online/foreground создания индекса. Всегда держите резервную стратегию отката.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone