Индексы: зачем и какие бывают
Почему запрос по миллиону документов может быть мгновенным или мучительно медленным.
Индекс — вспомогательная структура, которая позволяет находить документы по полю, не перебирая всю коллекцию.
Проблема: полный перебор
Без индекса запрос db.users.find({ email: "[email protected]" }) заставляет MongoDB прочитать каждый документ коллекции и сравнить поле — это называется collection scan. На сотне документов незаметно, на миллионах — катастрофа. Индекс решает это, как алфавитный указатель в книге: вместо листания всех страниц вы идёте сразу к нужной.
Создаём индекс: createIndex
Чтобы ускорить поиск по email, строим индекс по этому полю (1 — по возрастанию):
db.users.createIndex({ email: 1 })Теперь поиск по email идёт по индексу за логарифмическое время вместо полного перебора. Поле _id индексируется автоматически — поэтому поиск по нему и так быстрый.
Составной индекс: несколько полей
Если запросы часто фильтруют сразу по нескольким полям, строят составной (compound) индекс. Например, поиск заказов по городу и статусу:
db.orders.createIndex({ city: 1, status: 1 })Важен порядок полей. Такой индекс ускорит запросы по city и по city + status, но не поможет запросу только по status — это «правило префикса»: индекс работает слева направо. Поэтому первым ставят поле, по которому фильтруют чаще.
Уникальный индекс
Индекс умеет ещё и гарантировать уникальность значения — как UNIQUE в SQL. Запретим повтор email:
db.users.createIndex({ email: 1 }, { unique: true })Теперь вставка второго пользователя с тем же email вызовет ошибку дубликата. Это надёжная защита от дублей на уровне базы, а не только приложения.
Цена индексов
Индексы не бесплатны. Каждый индекс занимает память и замедляет запись: при вставке и обновлении базе нужно поддерживать ещё и индексы. Поэтому не индексируют всё подряд — только поля, по которым реально и часто фильтруют или сортируют. Правило: индекс под запрос, а не «на всякий случай».
Посмотреть индексы коллекции и удалить ненужный:
db.users.getIndexes()
db.users.dropIndex({ email: 1 })Итог
- Без индекса запрос перебирает всю коллекцию (collection scan); индекс делает поиск быстрым.
- Составной индекс работает по «правилу префикса» — порядок полей важен.
- Уникальный индекс запрещает дубликаты; за индексы платят памятью и скоростью записи — индексируют под реальные запросы.