Создание индексов MongoDB

MongoDBBeginner
Практиковаться сейчас

Введение

В этой лабораторной работе вы изучите основные методы создания и управления индексами в MongoDB. Индексы имеют решающее значение для оптимизации производительности базы данных, поскольку они позволяют базе данных находить и извлекать данные гораздо быстрее, чем при сканировании каждого документа в коллекции. Вы попрактикуетесь в создании однопольных, составных и уникальных индексов, анализируя их влияние на производительность запросов и управляя их жизненным циклом. К концу этой лабораторной работы вы получите твердое понимание того, как использовать индексы для повышения эффективности ваших запросов MongoDB.

Создание индекса по одному полю

На первом этапе вы подключитесь к MongoDB, создадите базу данных с примером коллекции, а затем создадите свой первый индекс по одному полю. Однопольный индекс повышает производительность запросов, которые фильтруют или сортируют по этому конкретному полю.

Сначала откройте MongoDB Shell, набрав mongosh в вашем терминале. Это подключит вас к серверу MongoDB, работающему в вашей среде.

mongosh

Как только вы окажетесь внутри MongoDB Shell, вы увидите приглашение >. Давайте создадим и переключимся на новую базу данных под названием indexlab. Все последующие команды в этой лабораторной работе будут выполняться в этой оболочке, если не указано иное.

use indexlab

Теперь давайте вставим несколько примеров документов в новую коллекцию под названием users. Эти данные будут использоваться на протяжении всей лабораторной работы.

db.users.insertMany([
  { name: "Alice", age: 28, email: "alice@example.com" },
  { name: "Bob", age: 35, email: "bob@example.com" },
  { name: "Charlie", age: 42, email: "charlie@example.com" }
]);

После того как наши данные будут готовы, давайте создадим индекс по полю name. Индекс по одному полю помогает ускорить запросы, которые ищут документы по этому полю.

db.users.createIndex({ name: 1 });

В приведенной выше команде { name: 1 } указывает, что индекс должен быть создан по полю name в порядке возрастания. Использование -1 создаст индекс в порядке убывания.

Чтобы убедиться, что индекс был создан, вы можете вывести список всех индексов для коллекции users.

db.users.getIndexes();

В выводе вы должны увидеть два индекса. Один — это индекс _id по умолчанию, создаваемый MongoDB для каждой коллекции, а другой — это индекс name_1, который вы только что создали.

[
  { "v": 2, "key": { "_id": 1 }, "name": "_id_" },
  { "v": 2, "key": { "name": 1 }, "name": "name_1" }
]

Создание составного индекса

Хотя однопольные индексы полезны, многие запросы фильтруются по нескольким полям. В таких случаях составной индекс, включающий несколько полей, может значительно повысить производительность. На этом этапе вы создадите составной индекс.

Продолжим в оболочке mongosh. Мы создадим составной индекс по полям age и name. Порядок полей в составном индексе важен. MongoDB может использовать этот индекс для поддержки запросов только по age или по age, а затем по name.

db.users.createIndex({ age: -1, name: 1 });

Эта команда создает индекс, который сначала сортирует документы по age в порядке убывания (-1), а затем, для документов с одинаковым возрастом, сортирует их по name в порядке возрастания (1).

Давайте добавим еще несколько документов, чтобы сделать нашу коллекцию более разнообразной для запросов.

db.users.insertMany([
  { name: "David", age: 28, email: "david@example.com" },
  { name: "Eve", age: 35, email: "eve@example.com" }
]);

Теперь снова просмотрите список индексов, чтобы увидеть ваш новый составной индекс.

db.users.getIndexes();

В выводе, помимо предыдущих, теперь будет включен индекс age_-1_name_1.

[
  { "v": 2, "key": { "_id": 1 }, "name": "_id_" },
  { "v": 2, "key": { "name": 1 }, "name": "name_1" },
  { "v": 2, "key": { "age": -1, "name": 1 }, "name": "age_-1_name_1" }
]

Этот составной индекс будет эффективно обслуживать запросы, которые фильтруют или сортируют по age, или по age, а затем по name.

Создание уникального индекса

Индексы также могут использоваться для обеспечения целостности данных. Уникальный индекс гарантирует, что индексированное поле (или поля) не содержит повторяющихся значений. На этом этапе вы создадите уникальный индекс для предотвращения дублирования адресов электронной почты в коллекции users.

Давайте создадим уникальный индекс по полю email. Это делается путем добавления опции { unique: true } при создании индекса.

db.users.createIndex({ email: 1 }, { unique: true });

Теперь, когда уникальный индекс установлен, MongoDB будет отклонять любые попытки вставить или обновить документ, если это приведет к дублированию значения в поле email.

Давайте протестируем это. Сначала попробуйте вставить документ с новым, уникальным адресом электронной почты. Это должно пройти успешно.

db.users.insertOne({ name: "Frank", age: 31, email: "frank@example.com" });

Затем попытайтесь вставить другой документ с существующим адресом электронной почты, например alice@example.com. Эта операция завершится неудачно. Блок try...catch позволяет увидеть ошибку, не отключаясь от оболочки mongosh.

try {
  db.users.insertOne({ name: "Fiona", age: 29, email: "alice@example.com" });
} catch (e) {
  print(e);
}

Команда выдаст ошибку, указывающую на нарушение уникальности ключа. В выводе будет сообщение типа E11000 duplicate key error collection.

Вы можете снова просмотреть свои индексы, чтобы увидеть свойство уникального ограничения.

db.users.getIndexes();

Обратите внимание на свойство unique: true в индексе email_1 в выводе.

[
  ...,
  {
    v: 2,
    key: { email: 1 },
    name: 'email_1',
    unique: true
  }
]

Анализ использования индекса с помощью explain()

Создание индексов — это только половина дела; вам также нужно убедиться, что MongoDB фактически использует их для ваших запросов. Метод explain() — это мощный инструмент для этой цели, предоставляющий подробную информацию о том, как выполняется запрос. Этот шаг покажет вам, как использовать explain(), чтобы убедиться, что MongoDB эффективно использует ваши существующие индексы.

Давайте проанализируем запрос, который находит пользователей определенного возраста. Поскольку у нас уже есть составной индекс age_-1_name_1 из предыдущего шага, MongoDB может использовать этот индекс для оптимизации запроса по полю age.

db.users.find({ age: 35 }).explain("executionStats");

В выводе найдите поле executionStats.stage внутри winningPlan. Вы должны увидеть значение IXSCAN, что означает "Index Scan" (Сканирование индекса). Это указывает на то, что MongoDB использует существующий составной индекс age_-1_name_1 для быстрого поиска соответствующих документов. Вы также должны увидеть, что totalDocsExamined соответствует количеству возвращенных документов, что демонстрирует эффективность использования составного индекса.

Чтобы лучше понять, как MongoDB выбирает индексы, давайте также протестируем запрос, который может использовать преимущества однопольного индекса name, созданного нами ранее.

db.users.find({ name: "Alice" }).explain("executionStats");

Этот запрос также должен показывать IXSCAN в качестве этапа выигрышного плана, подтверждая, что MongoDB использует индекс name_1, созданный нами на первом шаге.

Просмотр и удаление индексов

Последняя часть управления индексами — это знание того, как их перечислять и удалять, когда они больше не нужны. Неиспользуемые индексы по-прежнему потребляют дисковое пространство и увеличивают накладные расходы на операции записи, поэтому хорошей практикой является их очистка.

Сначала получим полный список всех индексов, которые вы создали до сих пор в коллекции users.

db.users.getIndexes();

Эта команда предоставляет исчерпывающий обзор вашей текущей конфигурации индексов. Предположим, вы решили, что составной индекс age_-1_name_1 больше не нужен. Вы можете удалить его с помощью метода dropIndex(), указав имя индекса.

db.users.dropIndex("age_-1_name_1");

После выполнения команды вы получите подтверждающее сообщение. Чтобы быть уверенным, вы можете перечислить индексы еще раз, чтобы убедиться, что он был удален.

db.users.getIndexes();

Индекс age_-1_name_1 больше не должен отображаться в списке.

Если вам нужно удалить все пользовательские индексы из коллекции (кроме индекса по умолчанию _id), вы можете использовать метод dropIndexes(). Эта команда является мощной, поэтому используйте ее с осторожностью.

// Пример: db.users.dropIndexes()

На этом завершаются основные операции по управлению индексами в MongoDB. Теперь вы можете выйти из оболочки mongosh.

exit;

Резюме

В этой лабораторной работе вы освоили основные навыки работы с индексами MongoDB. Вы начали с создания базового индекса по одному полю для ускорения простых запросов. Затем вы перешли к созданию составного индекса для оптимизации запросов, включающих несколько полей. Вы также научились обеспечивать целостность данных, создавая уникальный индекс. Кроме того, вы использовали метод explain(), чтобы анализировать планы запросов и подтверждать, что ваши индексы используются эффективно, наблюдая разницу в производительности между сканированием коллекции (collection scan) и сканированием индекса (index scan). Наконец, вы отработали управление индексами, перечисляя и удаляя их. Освоение этих методов индексирования является критически важным шагом на пути к созданию быстрых и масштабируемых приложений с использованием MongoDB.