Индексы SQL
Индекс — отдельная структура доступа к строкам. Он ускоряет некоторые чтения ценой места, обслуживания при записи и дополнительной сложности планирования.
B-tree
Наиболее распространенный индекс поддерживает равенство, диапазоны и упорядоченный проход:
CREATE INDEX idx_orders_user_created
ON orders (user_id, created_at DESC);Он подходит для запроса:
SELECT id, total, created_at
FROM orders
WHERE user_id = 42
AND created_at >= TIMESTAMP '2026-01-01 00:00:00'
ORDER BY created_at DESC;В составном B-tree важен порядок столбцов. Упрощенное правило «левого префикса» полезно, но не абсолютно: оптимизатор может использовать skip scan, bitmap scan и другие возможности конкретной СУБД.
Другие виды
- hash — равенство, если поддерживается реализацией;
- inverted/GiST/GIN-подобные структуры — массивы, документы, полнотекстовый поиск, геоданные;
- bitmap — аналитические сценарии и низкая кардинальность в некоторых СУБД;
- clustered/организация таблицы — физическая близость строк, но терминология отличается.
Покрывающий индекс
Если все нужные запросу данные доступны из индекса, СУБД иногда избегает чтения таблицы. Это зависит от видимости версий и реализации.
CREATE INDEX idx_orders_state_created
ON orders (state, created_at)
INCLUDE (id, total);INCLUDE поддерживается не везде. Широкий индекс занимает больше места и дороже обновляется.
Частичный и функциональный индекс
CREATE INDEX idx_orders_new_created
ON orders (created_at)
WHERE state = 'NEW';
CREATE INDEX idx_users_lower_email
ON users (LOWER(email));Это мощные, но диалект-зависимые инструменты. Предикат запроса должен соответствовать определению индекса.
Почему индекс не используют
- запрос возвращает большую долю таблицы;
- статистика устарела или неверно оценивает корреляцию;
- типы приводятся неудачно;
- над столбцом применена функция;
- ведущий столбец составного индекса не ограничен;
- последовательное чтение дешевле случайных обращений.
Цена индекса
- дополнительный I/O и CPU на
INSERT/UPDATE/DELETE; - блокировки и время создания;
- место на диске и в кэше;
- фрагментация/разрастание;
- риск дублирующих почти одинаковых индексов.
Связано: Селективность SQL, SQL оценка производительности, Оператор ORDER BY, Оператор LIKE.
Вопросы
Почему индекс не гарантирует ускорение? Оптимизатор выбирает самый дешевый по оценке план; чтение большой доли таблицы может быть быстрее scan.
Имеет ли значение порядок столбцов? Да: он определяет доступные префиксы, диапазон и порядок результата.
Что такое покрывающий индекс? Индекс, из которого можно получить все нужные запросу столбцы без обычного доступа к таблице при выполнении условий реализации.
Почему не индексировать каждый столбец? Запись, хранение и обслуживание подорожают, а многие индексы не будут полезны.
Помогает ли индекс для %text%? Обычный B-tree обычно нет; нужен специализированный индекс или полнотекстовый поиск.