Важливість індексації в MongoDB: реальний приклад

Індекси є важливими для оптимізації продуктивності запитів у MongoDB, особливо при роботі з великими наборами даних. Давайте розглянемо важливість індексації на реальному прикладі, зрозуміємо, як працює індексація, та вивчимо різні типи індексів, їхні варіанти використання та реалізацію.

Реальний приклад: записи рецептів

Уявіть собі медичний додаток, який керує 1 мільйоном записів рецептів. Без індекса запит на отримання рецептів за patientId займає близько 12 секунд, оскільки MongoDB виконує повне сканування колекції. Після створення індексу на полі patientId той самий запит займає лише близько 900 мілісекунд!

Чому така значна покращення?

  1. Сканування колекції: Без індекса MongoDB сканує кожен документ у колекції, щоб знайти відповідні записи.
  2. Індексований пошук: Завдяки індексу MongoDB використовує B-дерево для безпосереднього пошуку відповідних документів, що значно скорочує час виконання запиту.

Як працює індексація

Індекси в MongoDB реалізуються за допомогою B-дерева. Це гарантує:

  • Ефективний пошук: Запити звужують простір пошуку, проходячи по дереву.
  • Послідовність: Усі листяні вузли знаходяться на одному рівні, що забезпечує однаковий час пошуку.
  • Динамічні оновлення: B-дерева автоматично коригуються під час вставок або видалень, підтримуючи баланс.

Наприклад, при запиті за patientId B-дерево організовує значення ієрархічно, що дозволяє MongoDB отримати результати за логарифмічний час (O(log n)) замість лінійного часу (O(n)).

Типи індексів та варіанти використання

MongoDB підтримує різні типи індексів, кожен з яких призначений для конкретних варіантів використання:

  1. Індекс на одне поле:
  • Індексування одного поля.
  • Варіант використання: Швидкі пошуки за такими полями, як patientId або prescriptionId.
db.prescriptions.createIndex({ patientId: 1 });
  1. Комбінований індекс:
  • Індексування кількох полів.
  • Варіант використання: Запити, які включають більше ніж одне поле, наприклад, patientId та date.
  • Реалізація:
db.prescriptions.createIndex({ patientId: 1, date: -1 })
  1. TTL (Time-To-Live) індекс:
  • Автоматичне видалення документів після визначеного часу.
  • Варіант використання: Тимчасові дані, як-от журнали сесій або токени, що зникають.
  • Реалізація:
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 });
  1. Геопросторовий індекс:
  • Дозволяє виконувати геопросторові запити.
  • Приклад варіанту використання: Пошук найближчих лікарів або клінік.
  • Реалізація:
db.locations.createIndex({ location: "2dsphere" });

Геопросторовий індекс: реальний приклад.

Сценарій:

Вам потрібно знайти лікарів в межах 5-кілометрового радіусу від місцезнаходження пацієнта.

Виконання запиту з використанням $geoNear:

db.locations.aggregate([  
 {  
 $geoNear: {  
 near: { type: "Point", coordinates: [longitude, latitude] },  
 distanceField: "distance",  
 maxDistance: 5000,  
 spherical: true  
 }  
 }  
]);

Як використовувати геопросторові індекси з Spring Data Mongo?

  1. Додайте анотацію @GeoSpatialIndexed до поля location у вашому класі сутності:
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)   
private GeoJsonPoint location;
  1. Визначте метод репозиторію:
List findByLocationNear(Point location, Distance distance);

Викликайте метод у вашому сервісі:

Point patientLocation = new Point(longitude, latitude);
Distance radius = new Distance(5, Metrics.KILOMETERS);
List nearbyDoctors = doctorRepository.findByLocationNear(patientLocation, radius);
```

Додавання інших типів індексів через MongoRepository

Індекс на одне поле

Додайте анотацію @Indexed до відповідного поля у вашому класі сутності:

@Indexed  
private String patientId;

Комбінований індекс

Використовуйте анотацію @CompoundIndex для створення індексу на кількох полях:

@CompoundIndex(name = "patient_date_idx", def = "{'patientId': 1, 'date': -1}")  
public class Prescription {  
 private String patientId;  
 private Date date;  
}

TTL індекс

Використовуйте @Indexed з expireAfterSeconds для створення TTL індексу:

@Indexed(name = "session_expiry", expireAfterSeconds = 3600)  
private Date createdAt;

Конфігурація автоматичного створення індексів у Spring Boot:

Щоб увімкнути або вимкнути автоматичне створення індексів у MongoDB при використанні Spring Boot, додайте наступний рядок у ваш файл application.properties:

spring.data.mongodb.auto-index-creation=true

Установивши значення true, ви увімкнете автоматичне створення індексів при запуску програми, а значення false вимкне цю можливість.

Моніторинг та аналіз індексів

  1. Перегляд існуючих індексів:
db.prescriptions.getIndexes();
  1. Аналіз продуктивності запитів: Використовуйте Explain Plan для розуміння того, як MongoDB виконує запити:
db.prescriptions.find({ patientId: 12345 }).explain("executionStats");

Що відбувається, якщо є кілька індексів?

Якщо для запиту підходить кілька індексів, MongoDB використовує Query Planner для оцінки всіх кандидатних індексів і вибору найоптимізованішого. Цей процес включає:

  1. Генерація кандидатних планів: MongoDB генерує кілька планів виконання запитів на основі доступних індексів.
  2. Оцінка планів: Кожен план оцінюється з використанням евристик і оцінок витрат, таких як кількість перевірених документів і ефективність використання індексів.
  3. Вибір плану: Query Planner вибирає план з найменшими оціненими витратами на виконання.

Балансування витрат та переваг індексів

Хоча індекси покращують продуктивність запитів, вони мають свої недоліки:

  1. Навантаження на зберігання: Індекси займають додатковий простір на диску.
  2. Вплив на продуктивність запису: Операції вставки, оновлення та видалення виконуються повільніше, оскільки індекси повинні бути оновлені.

Плануйте індекси ретельно, враховуючи патерни запитів, і періодично переглядайте не використані індекси для оптимізації продуктивності.

Висновок

Індекси — це потужний інструмент для оптимізації запитів MongoDB, що дозволяє перетворити операції, які займають секунди, на мілісекунди. Розуміючи, як працює індексація, та використовуючи різні типи індексів, ви значно покращите продуктивність та масштабованість вашого додатку. Незалежно від того, чи працюєте ви з мільйонами записів рецептів або шукаєте найближчих лікарів, індексація є ключем до ефективного отримання даних.

Успіхів у роботі з індексами!

Перекладено з: Importance of Indexing in MongoDB: A Real-Life Example

Leave a Reply

Your email address will not be published. Required fields are marked *