> Что делать, если после добавления индекса селективность низкая и запрос остается медленным? (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: InDrive
Стек: Go
> Пример ответа
Если после добавления индекса селективность низкая и запрос остаётся медленным, нужно провести диагностику и рассмотреть альтернативные подходы.
-
Проверить план выполнения запроса через
EXPLAIN ANALYZE. Убедиться, что индекс действительно используется, а не происходит полное сканирование таблицы из-за неверной оценки стоимости. -
Оценить селективность - если индекс покрывает столбцы с большим количеством повторяющихся значений (например, пол "M"/"F"), он может быть неэффективен. В таком случае стоит:
- Добавить составной индекс с более селективным столбцом первым.
- Использовать частичный индекс (например,
WHERE status = 'active'), если запросы фильтруют только подмножество данных.
-
Рассмотреть покрывающий индекс - включить все столбцы, участвующие в
SELECT,WHERE,ORDER BY, чтобы избежать обращений к таблице (Index Only Scan). -
Проверить статистику - возможно, устаревшая статистика вводит планировщик в заблуждение. Выполнить
ANALYZEдля таблицы. -
Оптимизировать запрос - переписать его, используя JOIN вместо подзапросов, или добавить хинты для планировщика (например,
/*+ IndexScan */в PostgreSQL). -
Аппаратные ограничения - если данные не помещаются в буферный кэш, индекс может не ускорить запрос из-за частых дисковых чтений. Увеличить
shared_buffersили добавить память.
Пример на Go с использованием database/sql для проверки плана:
GOrows, err := db.Query("EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'pending'")if err != nil {log.Fatal(err)}defer rows.Close()for rows.Next() {var plan stringrows.Scan(&plan)fmt.Println(plan)}
Если после всех шагов запрос всё ещё медленный, возможно, стоит пересмотреть архитектуру: денормализовать данные, использовать кэш (Redis) или перейти на колоночное хранение для аналитических запросов.
> Похожие задачи по Go
Для чего используется SELECT FOR UPDATE?
Приходилось ли менять уровни изоляции транзакций?
Какие стратегии пагинации можно использовать вместо LIMIT OFFSET?
Что такое пагинация?
> Похожие задачи по backend
Для чего используется SELECT FOR UPDATE?
Приходилось ли менять уровни изоляции транзакций?
Какие стратегии пагинации можно использовать вместо LIMIT OFFSET?
Что такое пагинация?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью