Важен ли порядок столбцов в составном индексе и условиях запроса
Что проверяют
Знаете ли вы правило левого префикса и отличаете ли порядок колонок в индексе от порядка условий в WHERE. Следом обычно дают конкретный запрос и просят выбрать индекс, иногда с диапазоном или сортировкой.
Как отвечать
Короткий ответ: порядок в индексе важен, порядок условий в запросе нет.
- левый префикс: B-tree индекс
(city, age)отсортирован сначала поcity, внутри поage. Он помогает запросам поcityи по паре, но не запросу только поage: строки с нужным возрастом разбросаны по всему индексу; - порядок в
WHERE:age = 30 AND city = 'Tver'иcity = 'Tver' AND age = 30для оптимизатора одно и то же, он сам переставит условия; - равенство перед диапазоном: в индексе
(created_at, status)приcreated_at > ? AND status = ?поиск идёт только по дате, а статус проверяется уже внутри найденного диапазона. Индекс(status, created_at)отработает точнее; - сортировка: индекс
(user_id, created_at)обслуживаетWHERE user_id = ? ORDER BY created_at DESC LIMIT 20без отдельной сортировки; - исключения: MySQL 8 и PostgreSQL 18 умеют skip scan и могут использовать индекс без условия на первую колонку, если в ней мало различных значений. Проектировать индексы в расчёте на это не стоит.
В Java-проекте индекс обычно объявляют в миграции Flyway или Liquibase, реже через @Table(indexes = @Index(columnList = "city, age")). Проверка всегда одна: EXPLAIN ANALYZE на реальном запросе, который генерирует Hibernate, а не на запросе, написанном руками по памяти.
Где спотыкаются
Утверждают, что запрос с условиями в «неправильном» порядке не возьмёт индекс. Это миф: важен только набор колонок в условии.
Механически ставят самую селективную колонку первой. Для двух равенств порядок почти не влияет на скорость, решают другие запросы: какая колонка встречается в условии одна, где диапазон, по чему сортируют.
Создают (a, b) и рядом отдельный индекс (a). Второй дублирует префикс первого и только замедляет запись.