Ответ
Да, я использовал составные индексы для оптимизации запросов к базам данных.
Составной индекс — это индекс, который строится сразу по нескольким полям (колонкам) в определенном порядке. Он позволяет базе данных эффективно выполнять запросы, которые фильтруют или сортируют данные по этим полям.
Когда их стоит применять:
-
Фильтрация по нескольким полям: Когда запросы часто содержат условия по нескольким полям одновременно. Например, найти всех пользователей из города
X
со статусомactive
.SELECT * FROM users WHERE city = 'X' AND status = 'active';
Для этого запроса идеален составной индекс по
(city, status)
. -
Покрытие запроса (Covering Index): Когда все поля, необходимые для запроса (в
SELECT
,WHERE
,ORDER BY
), содержатся в самом индексе. В этом случае базе данных не нужно обращаться к самой таблице, что значительно ускоряет выполнение запроса. -
Фильтрация и сортировка: Когда запрос фильтрует по одному полю и сортирует по другому. Например, найти все статьи пользователя с
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
}