В прошлом уроке мы соединяли коллекции и считали новые поля. Все наши запросы до сих пор работали на девяти книгах, и любой отвечал мгновенно. В настоящем магазине книг десятки тысяч, а заказов миллионы. Тогда важно не только что спросить, но и как база будет искать ответ. Сегодня знакомимся с главным инструментом скорости: индексом.
Предметный указатель
Нужно найти в толстом учебнике всё про рекурсию. Можно листать с первой страницы до последней и читать каждую. А можно открыть предметный указатель в конце книги: слова там стоят по алфавиту, рядом номера страниц. Находишь «рекурсия», видишь «стр. 45, 112, 304» и открываешь только их.
Индекс в MongoDB это такой указатель для коллекции. Значения выбранного поля лежат в нём по порядку, рядом ссылки на документы. Чтобы найти книги жанра «роман», серверу не нужно перебирать все документы: он находит «роман» в упорядоченном списке и сразу идёт к нужным книгам.
Без индекса сервер делает то же, что читатель без указателя: перебирает всю коллекцию. Такой перебор называется полным просмотром коллекции. Как его увидеть в цифрах, разберём в следующем уроке.
Если ты прошёл вводный урок про индексы в PostgreSQL, идея та же самая. В обеих базах обычный индекс устроен как B-дерево.
Индекс, который есть всегда
Посмотрим, какие индексы уже есть у книг:
db.books.getIndexes()
[ { v: 2, key: { _id: 1 }, name: '_id_' } ]
Один индекс уже есть, хотя мы его не создавали. MongoDB строит индекс по _id для каждой коллекции сама и не даёт его удалить. Поэтому поиск по _id быстрый всегда, а два документа с одинаковым _id в коллекцию не попадут: этот индекс уникальный.
В ответе три поля: v это версия формата индекса, key говорит, по какому полю и в каком порядке он построен (1 по возрастанию), а name это имя индекса.
Создаём индекс
Магазин часто показывает книги одного жанра. Создадим индекс по genre:
db.books.createIndex({ genre: 1 })
genre_1
createIndex принимает описание: поле и направление. Возвращает он имя, которое MongoDB собрала сама: имя поля и направление через подчёркивание. Если индекс с таким описанием уже есть, повторный вызов ничего не сломает и вернёт то же имя.
Индекс можно построить и по вложенному полю, и по нескольким полям сразу:
db.books.createIndex({ 'author.name': 1, year: -1 })
author.name_1_year_-1
Это составной индекс: книги упорядочены по имени автора, а у одного автора от новых к старым. Он поможет странице «все книги автора, сначала свежие». Как правильно выбирать порядок полей в составном индексе, разберём позже в разделе, в кластере про индексы и производительность.
Теперь индексов три:
[
{ v: 2, key: { _id: 1 }, name: '_id_' },
{ v: 2, key: { genre: 1 }, name: 'genre_1' },
{
v: 2,
key: { 'author.name': 1, year: -1 },
name: 'author.name_1_year_-1'
}
]
Имя можно задать и своё, вторым аргументом: db.books.createIndex({ title: 1 }, { name: 'by_title' }) вернёт by_title.
урок из курса
Урок из курса «MongoDB с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.