Индексы в MongoDB: создание, виды и лучшие практики

TL;DR
Индексы в MongoDB ускоряют чтение и селекцию данных, но увеличивают стоимость записи и хранения. Научитесь создавать одиночные, multikey и составные индексы, проверять их эффект и выбирать стратегию по нагрузке приложения.
Важно: MongoDB по умолчанию создаёт индекс по полю _id — это обеспечивает быстрый поиск по идентификатору документа.
Что такое индекс в MongoDB
Индекс — это вспомогательная структура данных, которая упорядочивает значения полей коллекции для быстрой выборки. Она позволяет БД выполнять поиск и сортировку без полного сканирования коллекции.
Определение в одну строку: индекс — это таблица указателей на документы, отсортированная по значению одного или нескольких полей.
Ключевые эффекты индексирования:
- Быстрые операции чтения по индексируемым полям.
- Сортировка без дополнительной операции sort, если индекс уже содержит порядок.
- Возможность задать уникальность для предотвращения дубликатов.
Когда индексы помогают и когда нет
- Полезно: частые фильтры по конкретным полям, сортировка по дате, поиск по уникальным ключам (например, email, username).
- Неэффективно: малое количество уникальных значений (low cardinality), частые массовые вставки без пакетирования, запросы, которые возвращают почти всю коллекцию.
Пример неэффективности: индекс по полю boolean часто бессмыслен — селект указывает на ~50% документов и индекс не экономит чтение.
Как создать индекс в MongoDB
Перед созданием индексов убедитесь, что у вас есть запущенный сервер MongoDB и выбранная база данных и коллекция.
Примеры в mongo shell.
Создать одиночный индекс по полю age, сортировка по убыванию:
db.userCollection.createIndex({age: -1})Пояснение: значение -1 означает сортировку по убыванию; 1 означает по возрастанию.
Если вы создадите индекс с нужным порядком сортировки, при выполнении запроса сортирование может быть выполнено за счёт индекса и не потребует дополнительной памяти.
Выбор базы данных
use MUOСоздание одиночного индекса
Одиночный индекс по имени пользователя, сортировка по убыванию:
db.collectionName.createIndex({username: -1})Multikey индекс
Multikey индекс нужен, если поле — массив или вложенный объект и вы хотите индексировать элементы массива.
Пример: индекс по росту пользователей внутри массива user:
db.customers.createIndex({"user.height": 1})MongoDB создаст отдельный индексный ключ для каждого элемента массива.
Составной индекс
Если запрос сочетает фильтры по нескольким полям, часто полезен составной (compound) индекс.
Пример простого составного индекса по адресу и типу продукта:
db.customer.createIndex({address: 1, products: 1})По умолчанию MongoDB сформирует имя индекса из полей, разделённых подчёркиванием. Чтобы задать читаемое имя:
db.customers.createIndex({location: 1, products: 1, weight: -1}, {name: "myCompoundIndex"})Просмотр всех индексов коллекции
db.collectionName.getIndexes()Команда вернёт массив объектов с описанием каждого индекса, включая имя, ключи и опции.
Практическая методология выбора индекса (мини‑метод)
- Соберите метрики запросов: какие поля используются в фильтрах и сортировках.
- Отсортируйте поля по частоте использования и селективности (сколько уникальных значений).
- Для частых точечных запросов создайте одиночные индексы по этим полям.
- Для запросов с несколькими полями создайте составной индекс в порядке, соответствующем использованию в фильтре и сортировке.
- Тестируйте план выполнения (explain) и измеряйте latency и I/O.
- Ревью: удаляйте неиспользуемые индексы, чтобы снизить накладные расходы на записи.
Проверка эффективности: explain и профилирование
Всегда проверяйте, как запрос использует индекс:
db.collectionName.find({age: {$gt: 50}}).sort({date: -1}).explain("executionStats")explain возвращает план выполнения и показывает, использовал ли MongoDB индекс или сделал COLLSCAN. По executionStats можно увидеть количество прочитанных документов и операций.
Типичные ошибки и когда индексы «не работают» (контрпримеры)
- Индекс по полю с малой кардинальностью (например, boolean) почти не ускорит запрос.
- Неправильный порядок полей в составном индексе — запрос может не использовать индексовую префиксную часть.
- Создание слишком большого числа индексов удорожает вставки и обновления.
- Запросы с функциями над полем (например, вычисления в фильтре) не используют индекс.
Альтернативные подходы и когда их применять
- Кэширование в памяти (Redis) для быстрого доступа к результатам частых запросов.
- Денормализация: хранить предвычисленные поля или агрегаты рядом с документом.
- Aggregation pipeline с материализованными результатами для сложных аналитических задач.
- TTL‑индексы для автоматического удаления устаревших данных.
Ментальные модели и эвристики
- Heuristic 1: при частоте запросов > 1/sec по полю — подумайте про индекс.
- Heuristic 2: высокая селективность -> индекс полезен; низкая селективность -> бесполезен.
- Heuristic 3: если индекс улучшает латентность чтения, но ухудшает важную подачу записей — оцените компромисс.
Ролевые чеклисты
Разработчик:
- Определить поля для фильтрации и сортировки.
- Написать тестовые запросы и выполнить explain.
- Предложить индексы и проверить влияние на вставки.
DBA / Администратор БД:
- Проверить суммарный объём индексов и влияние на IOPS.
- Настроить расписание создания/удаления индексов в maintenance window.
- Мониторить пропускную способность и latencies операции записи.
Менеджер продукта:
- Оценить требования к SLA для latency чтения и записи.
- Утвердить компромиссы между скоростью чтения и стоимостью хранения.
Сниппет / шпаргалка по командам
use MUO
// Создать одиночный индекс
db.users.createIndex({age: -1})
// Multikey индекс
db.collection.createIndex({"tags": 1})
// Составной индекс с именем
db.orders.createIndex({userId: 1, createdAt: -1}, {name: "user_createdAt_idx"})
// Список индексов
db.orders.getIndexes()
// Удалить индекс по имени
db.orders.dropIndex("user_createdAt_idx")
// Проверить план выполнения
db.orders.find({userId: 123}).explain("executionStats")Критерии приёмки (что проверить после создания индекса)
- Запросы, для которых создавался индекс, используют этот индекс (explain показывает IDXSCAN).
- Latency запросов снизился до ожидаемого уровня.
- Нагрузка на запись не выросла сверх допустимой.
- Потребление дискового пространства индексами соответствует ожиданиям.
Пример использования: сортировка по дате без sort
Если требуется часто получать записи по убыванию даты, создайте индекс с порядком сортировки:
db.events.createIndex({date: -1})После этого запрос
db.events.find({type: "login"})может возвращать документы уже в нужном порядке без операции sort.
Decision flowchart для выбора типа индекса
flowchart TD
A[Какие поля в запросах?] --> B{Поле одно или массив?}
B -->|Одиночное поле| C[Одиночный индекс]
B -->|Массив или вложенное| D[Multikey индекс]
A --> E{Несколько полей}
E -->|Частые фильтры и сортировка| F[Составной индекс]
E -->|Редко комбинируются| G[Несколько одиночных индексов]
C --> H[Проверить explain и метрики]
D --> H
F --> H
G --> HФакто-бокс
- MongoDB создаёт индекс по полю _id по умолчанию.
- Индексы улучшают чтение, но увеличивают затрату на вставки и обновления.
- Multikey‑индекс пригоден для массивов и создаёт ключи для каждого элемента.
Риски и смягчения
- Риск: слишком много индексов замедляет запись. Смягчение: мониторить write latency и удалять редко используемые индексы.
- Риск: неправильный порядок полей в составном индексе. Смягчение: тестировать explain и проверять использование префикса.
Глоссарий (1 строка)
- Индекс: структура для быстрого доступа к документам по значению поля.
- Multikey: индекс для полей, содержащих массивы или вложенные документы.
- Составной индекс: индекс по нескольким полям, учитывающий порядок полей.
Заключение
Индексы — ключевой инструмент оптимизации запросов в MongoDB. Они позволяют значительно сократить время чтения и упростить сортировки, но требуют компромисса с затратами на запись и дисковое пространство. Применяйте методологию: анализируйте частоту и селективность запросов, создавайте индексы по приоритету и обязательно проверяйте план выполнения с помощью explain.
Краткий план действий:
- Собрать профили запросов.
- Выбрать кандидатов на индексацию.
- Создать индекс в тестовой среде.
- Измерить влияние и утвердить изменение в продакшене.
Похожие материалы
Отключить рекламу в Windows 11
Как собрать кастомный Mac на сайте Apple
Как использовать профили в Firefox
Стриминг Xbox на Android через Remote Play
Личный бренд в интернете: шаг за шагом