Как правильно определить порядок полей в составном (композитном) индексе базы данных?

Ответ

Порядок полей в составном индексе критически важен для производительности запросов и определяется в первую очередь структурой ваших WHERE и ORDER BY выражений, а не только селективностью (кардинальностью) данных.

Основное правило: Поля в индексе должны идти в том же порядке, в котором они используются в WHERE.

Представьте индекс как отсортированную телефонную книгу. Индекс по (фамилия, имя) позволяет быстро найти:

  • Всех с фамилией Иванов.
  • Конкретного Иванова Ивана.

Но он бесполезен для быстрого поиска всех людей с именем Иван без указания фамилии.

Рекомендации по порядку полей:

  1. Равенство (=, IN): Сначала идут поля, которые фильтруются по точному значению.
  2. Диапазон (>, <, BETWEEN): Затем поля, используемые в диапазонах. В одном индексе эффективно может использоваться только одно поле с диапазоном.
  3. Сортировка (ORDER BY): В конце — поля для сортировки, если направление сортировки в запросе и в индексе совпадает.

Пример:

Для запроса SELECT * FROM users WHERE country = 'RU' AND city = 'Moscow' ORDER BY registration_date; идеальным будет индекс:

-- Сначала поля для точного поиска, затем для сортировки
CREATE INDEX idx_users_country_city_reg_date ON users(country, city, registration_date);

Такой индекс будет малоэффективен или не будет использоваться для запросов, где фильтрация идет только по city или registration_date.

В Go при использовании ORM (например, GORM) это выглядит так:

db.Model(&User{}).AddIndex("idx_users_country_city_reg_date", "country", "city", "registration_date")