Ответ
Порядок полей в составном индексе критически важен для производительности запросов и определяется в первую очередь структурой ваших WHERE и ORDER BY выражений, а не только селективностью (кардинальностью) данных.
Основное правило: Поля в индексе должны идти в том же порядке, в котором они используются в WHERE.
Представьте индекс как отсортированную телефонную книгу. Индекс по (фамилия, имя) позволяет быстро найти:
- Всех с фамилией
Иванов. - Конкретного
Иванова Ивана.
Но он бесполезен для быстрого поиска всех людей с именем Иван без указания фамилии.
Рекомендации по порядку полей:
- Равенство (
=,IN): Сначала идут поля, которые фильтруются по точному значению. - Диапазон (
>,<,BETWEEN): Затем поля, используемые в диапазонах. В одном индексе эффективно может использоваться только одно поле с диапазоном. - Сортировка (
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") Ответ 18+ 🔞
А, слушай, вот эта тема с порядком полей в индексе — это вообще пиздец какой важный момент, а многие его на хуй не кладут! Думают, накидал полей в CREATE INDEX и всё, магия сама произойдёт. Хуй там! Это как телефонную книгу, блядь, пытаться читать с конца по имени, когда она отсортирована по фамилии. Ни хуя не найдёшь, только волнение ебать почувствуешь.
Вот смотри, представь себе индекс как эту самую книгу, но для базы данных. Создал ты индекс на (фамилия, имя). Ну, окей, найти «Иванова Ивана» — раз плюнуть. Или всех Ивановых — тоже легко. А попробуй найти всех Вань по имени, не зная фамилии! Пиздец, да? Придётся всю книгу, сука, листать, а это и есть full scan, овердохуища времени убьёт.
Так как же, блядь, правильно? Всё просто, как три копейки, но от этого не менее важно.
- Точные совпадения вперёд! (
=,IN). Те поля, по которым ты ищешь конкретное значение — они в начало индекса. Это как сначала выбрать страну, потом город. Без этого нихуя не работает. - Диапазоны — потом! (
>,<,BETWEEN). Их ставь после точных. И запомни, хитрая жопа, — эффективно в одном запросе обычно работает только один такой диапазонный предикат из индекса. Остальные — похуй. - Сортировка — в хвост! (
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);
Видишь логику? Сначала то, что ищем точно (country, city), потом то, по чему сортируем (registration_date). База возьмёт этот индекс, как родной, и выдаст всё мгновенно.
А если ты, мудак, сделаешь индекс на (city, registration_date, country) и попробуешь искать по стране? Хуй с горы! Индекс будет нихуя не полезен, потому что искать по country без city — всё равно что искать Вань в телефонной книге.
В Go, если ты через GORM это делаешь, выглядеть будет так же примитивно:
db.Model(&User{}).AddIndex("idx_users_country_city_reg_date", "country", "city", "registration_date")
Вот и вся наука. Не выёбывайся, ставь поля в том порядке, в котором их используешь в WHERE. И тогда твои запросы будут летать, а не ебать мозг с ожиданием.