> Какой индекс предложить для запроса с условиями по курсу студента и полу и почему (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Wildberries
Стек: Go
> Пример ответа
Короткий ответ
Предложу композитный индекс (course_id, gender) или (gender, course_id) - выбор зависит от селективности и частоты запросов. Для типичного сценария "все студенты конкретного курса с фильтром по полу" оптимален (course_id, gender), так как первое условие максимально сужает выборку, а второе добирает остаток. Если пол фильтруется чаще как самостоятельное условие - лучше начать с (gender, course_id). В PostgreSQL это B-tree индекс, в MySQL - тоже, если движок InnoDB.
Подробное объяснение
Индекс выбирается исходя из того, какие условия в WHERE наиболее селективны и как часто встречаются в запросах. Для запроса вида WHERE course_id = ? AND gender = ? композитный индекс позволяет:
- использовать оба условия для доступа к строкам, а не фильтровать после чтения;
- избежать сортировки, если есть
ORDER BYпо тем же колонкам.
Порядок колонок в композитном индексе критичен: B-tree позволяет эффективно использовать префикс индекса. Если индекс (course_id, gender), то он работает для запросов с course_id отдельно и с course_id + gender вместе. Индекс (gender, course_id) - для gender отдельно и для пары. Выбор зависит от того, какие запросы чаще: "все студенты курса" или "все студенты по полу".
Если селективность course_id высокая (например, 1000 курсов на 100k студентов), то (course_id, gender) даст меньше чтений. Если пол почти равномерен (50/50), то gender первым колонкой бесполезен для сужения - он лишь добавит overhead на запись. В этом случае лучше (course_id, gender).
Дополнительно стоит учесть:
- если запросы всегда содержат оба условия, порядок не критичен для производительности чтения, но влияет на возможность покрытия других запросов;
- если есть
ORDER BY course_idилиGROUP BY course_id, индекс(course_id, gender)поможет избежать сортировки; - для MySQL с InnoDB вторичный индекс автоматически включает primary key, поэтому лишние колонки в индексе увеличивают размер.
На практике
Для Go-бэкенда с PostgreSQL типичный сценарий - репозиторий с методами вида GetStudentsByCourseAndGender. Здесь важно:
- проверить план запроса через
EXPLAIN ANALYZE- убедиться, что используется Index Scan, а не Seq Scan; - если таблица большая, рассмотреть partial index, например, только для активных студентов, если пол фильтруется редко;
- не создавать отдельные индексы на
course_idиgenderпо отдельности, если есть композитный - они будут дублировать префикс.
В MySQL с InnoDB стоит помнить про ограничение на длину ключа (3072 байта для DYNAMIC row format) - для course_id и gender это не проблема, но если добавить student_name varchar(255) - уже может быть.
Пример кода
SQL-- PostgreSQLCREATE INDEX idx_course_gender ON students (course_id, gender);-- проверка планаEXPLAIN ANALYZESELECT * FROM studentsWHERE course_id = 42 AND gender = 'female';
GO// Go: метод репозиторияfunc (r *StudentRepo) GetByCourseAndGender(ctx context.Context, courseID int, gender string) ([]Student, error) {rows, err := r.db.QueryContext(ctx, `SELECT id, name, course_id, genderFROM studentsWHERE course_id = $1 AND gender = $2`, courseID, gender)// обработка ошибок и сканирование}
Как отвечать на собеседовании
Начни с уточнения: какой СУБД пользуетесь, какой объём таблицы, какие ещё запросы есть к этой таблице. Затем предложи композитный индекс и объясни порядок колонок через селективность. Упомяни, что проверил бы через EXPLAIN. Покажи понимание trade-off: индекс ускоряет чтение, но замедляет запись и увеличивает размер. Если спросят про покрывающий индекс - скажи, что можно добавить student_name в INCLUDE (PostgreSQL) или в конец индекса (MySQL), если запросы часто возвращают только эти колонки.
Что проверяет интервьюер
- понимание устройства B-tree индекса и понятия селективности;
- умение обосновать порядок колонок в композитном индексе;
- знание trade-off между скоростью чтения и стоимостью записи;
- практический опыт работы с
EXPLAINи настройкой индексов; - способность задавать уточняющие вопросы перед ответом.
Типичные ошибки
- предложить два отдельных индекса на
course_idиgender- СУБД сможет использовать только один (в большинстве случаев), второй останется неиспользуемым; - поставить
genderпервым без анализа селективности - если пол распределён примерно поровну, индекс будет почти бесполезен; - забыть про влияние на
INSERT/UPDATE- каждый индекс увеличивает время записи; - не упомянуть проверку через
EXPLAIN- это признак отсутствия практики; - предложить hash index для диапазонных условий - он не поддерживает сравнения и сортировку.
> Похожие задачи по Go
Чем должна отличаться новая компания от текущей
Что хотел бы поменять в профессии или работе
Как использовать hint parallel для ускорения запросов в Oracle
Какой параметр использовать для партицирования, который не меняется со временем и помогает оптимизировать запрос
> Похожие задачи по backend
Чем должна отличаться новая компания от текущей
Что хотел бы поменять в профессии или работе
Как использовать hint parallel для ускорения запросов в Oracle
Какой параметр использовать для партицирования, который не меняется со временем и помогает оптимизировать запрос
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью