Что такое составные индексы (compound indexes) и в каких случаях их стоит применять?

Ответ

Да, я использовал составные индексы для оптимизации запросов к базам данных.

Составной индекс — это индекс, который строится сразу по нескольким полям (колонкам) в определенном порядке. Он позволяет базе данных эффективно выполнять запросы, которые фильтруют или сортируют данные по этим полям.

Когда их стоит применять:

  1. Фильтрация по нескольким полям: Когда запросы часто содержат условия по нескольким полям одновременно. Например, найти всех пользователей из города X со статусом active.

    SELECT * FROM users WHERE city = 'X' AND status = 'active';

    Для этого запроса идеален составной индекс по (city, status).

  2. Покрытие запроса (Covering Index): Когда все поля, необходимые для запроса (в SELECT, WHERE, ORDER BY), содержатся в самом индексе. В этом случае базе данных не нужно обращаться к самой таблице, что значительно ускоряет выполнение запроса.

  3. Фильтрация и сортировка: Когда запрос фильтрует по одному полю и сортирует по другому. Например, найти все статьи пользователя с user_id = 123 и отсортировать их по дате публикации.

    SELECT * FROM articles WHERE user_id = 123 ORDER BY created_at DESC;

    Здесь поможет индекс по (user_id, created_at).

Ключевые аспекты использования:

  • Порядок полей в индексе критически важен. Индекс (A, B) может быть использован для запросов с фильтрацией по A или по (A, B), но не для запросов, где фильтрация идет только по B.
  • Этот концепт применим как к NoSQL базам (например, MongoDB), так и к реляционным (PostgreSQL, MySQL).
  • Для проверки того, что база данных использует нужный индекс, всегда следует использовать команду EXPLAIN (или explain() в MongoDB).

Пример создания в MongoDB с помощью Go-драйвера:

import (
    "context"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "gopkg.in/mgo.v2/bson"
)

func createCompoundIndex(collection *mongo.Collection) error {
    // Создаем индекс по полю 'user_id' (по возрастанию) и 'score' (по убыванию)
    indexModel := mongo.IndexModel{
        Keys: bson.D{
            {Key: "user_id", Value: 1},  // 1 для сортировки по возрастанию
            {Key: "score", Value: -1}, // -1 для сортировки по убыванию
        },
    }
    _, err := collection.Indexes().CreateOne(context.Background(), indexModel)
    return err
}