Составные индексы: индекс по нескольким столбцам
Почему один индекс — это хорошо, а два — лучше? 🔥
Обычные индексы — как соло-исполнители: работают отлично, но только по одному запросу. Составные индексы — это уже целый оркестр, где несколько столбцов играют в идеальной гармонии! Вместе они ускоряют запросы, которые фильтруют или сортируют данные по нескольким полям сразу.
Пример проблемы из реальной жизни:
-- Таблица заказов интернет-магазина
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
order_date DATE,
status VARCHAR(20),
total_amount DECIMAL(10,2)
);
Если часто ищут заказы конкретного пользователя с определённым статусом — простой индекс по user_id не даст максимальной скорости.
Анатомия составного индекса 🧠
Составной индекс создаётся на два и более столбцов. Порядок столбцов в индексе критически важен — как порядок букв в алфавите!
Создаём супер-индекс:
CREATE INDEX idx_user_status ON orders(user_id, status);
Теперь запрос
SELECT * FROM orders
WHERE user_id = 42 AND status = 'completed';
будет летать как ракета! 🚀
Волшебные правила порядка столбцов ✨
1️⃣ Принцип левого края: Индекс (A,B,C) работает для запросов с:
AA AND BA AND B AND C
Но не для: B AND C или просто C.
2️⃣ Сортируй правильно: Если часто сортируете по total_amount, добавьте его в индекс:
CREATE INDEX idx_user_status_amount ON orders(user_id, status, total_amount);
Теперь этот запрос будет мгновенным:
SELECT * FROM orders
WHERE user_id = 42 AND status = 'completed'
ORDER BY total_amount DESC;
Живые примеры из практики 💼
Кейс 1: Социальная сеть
-- Индекс для быстрого поиска друзей онлайн
CREATE INDEX idx_friends_online ON friendships(user_id, friend_id, is_online)
WHERE is_online = true;
Кейс 2: Логи событий
-- Супер-индекс для аналитики
CREATE INDEX idx_logs_dates ON server_logs(server_id, event_date, event_type);
Когда составные индексы не помогут? ⚠️
1. Если условия в WHERE не используют префикс индекса:
-- Не использует индекс idx_user_status!
SELECT * FROM orders WHERE status = 'completed';
2. При использовании OR вместо AND:
-- Неэффективно, даже с индексом
SELECT * FROM orders
WHERE user_id = 42 OR status = 'completed';
Эксперимент: замеряем разницу ⏱️
Проведите тест на своей базе:
-- Без индекса
EXPLAIN ANALYZE SELECT * FROM large_table WHERE col1 = 'A' AND col2 = 'B';
-- С индексом
CREATE INDEX idx_col1_col2 ON large_table(col1, col2);
EXPLAIN ANALYZE SELECT * FROM large_table WHERE col1 = 'A' AND col2 = 'B';
Разница в скорости может достигать 1000 раз! Это не магия — это правильно построенные индексы. 🎩✨
Продвинутые фишки для профи 🚀
1. Инклюдированные столбцы (PostgreSQL):
CREATE INDEX idx_cover ON orders(user_id) INCLUDE (status, total_amount);
2. Частичные индексы для горячих данных:
-- Только для активных заказов
CREATE INDEX idx_active_orders ON orders(user_id)
WHERE status NOT IN ('cancelled', 'completed');
3. Многоколоночная сортировка:
-- Индекс для сложной сортировки
CREATE INDEX idx_sorting_master ON products(category, price DESC, rating DESC);
Как стать повелителем индексов? 🧙♂️
- Анализируйте частые запросы через
EXPLAIN ANALYZE - Начинайте с самых "тяжёлых" запросов
- Проверяйте избирательность столбцов (чем уникальнее — тем левее)
- Используйте покрывающие индексы для частых SELECT
Помните: каждый новый индекс замедляет INSERT/UPDATE. Баланс — ключ к успешной базе! ⚖️