> Что такое селективность данных в базах данных (Go)
Уровень: junior · Роль: backend · Категория: Технические вопросы
Компании: VK
Стек: Go
> Пример ответа
Короткий ответ
Селективность данных - это метрика, показывающая, какая доля строк таблицы будет отобрана по условию запроса. Она вычисляется как отношение количества строк, удовлетворяющих условию, к общему количеству строк. Высокая селективность означает, что условие отбирает мало строк, низкая - много. Селективность напрямую влияет на выбор плана выполнения запроса: при высокой селективности оптимизатор, скорее всего, использует индекс, при низкой - full scan.
Подробное объяснение
Селективность - ключевое понятие для понимания работы оптимизатора запросов. Она определяется для каждого предиката в WHERE, JOIN или HAVING.
Формально: селективность = количество уникальных значений столбца / общее количество строк. Например, для столбца id с 1 000 000 уникальных значений на 1 000 000 строк селективность = 1.0 (максимальная). Для столбца is_deleted с двумя значениями (true/false) селективность = 0.000002 - крайне низкая.
Оптимизатор использует статистику по распределению данных (гистограммы, количество NULL, density) для оценки селективности каждого предиката. На основе этих оценок он выбирает стратегию:
- Высокая селективность (близка к 1.0): условие отбирает мало строк - выгодно использовать индекс, чтобы не сканировать всю таблицу.
- Низкая селективность (близка к 0): условие отбирает много строк (например, 50% таблицы) - full scan часто быстрее, чем чтение индекса и последующие random access к таблице.
Важно: селективность зависит не только от столбца, но и от конкретного значения в условии. Для столбца с неравномерным распределением (например, 90% строк имеют значение status = 'active') селективность по status = 'active' будет низкой, а по status = 'archived' - высокой.
В PostgreSQL, MySQL, Oracle оптимизатор хранит статистику по каждому столбцу и обновляет её через ANALYZE / auto-analyze. Устаревшая статистика - частая причина деградации производительности.
На практике
Для backend-разработчика на Go понимание селективности важно при:
- Проектировании индексов - индекс имеет смысл только для столбцов с высокой селективностью. Индекс по
is_deletedпочти бесполезен. - Написании запросов - если условие по низкоселективному столбцу комбинируется с высокоселективным, порядок условий в WHERE не влияет на план (оптимизатор сам решает), но составной индекс нужно строить от высокоселективного к низкоселективному.
- Диагностике медленных запросов - если запрос с
WHERE status = 'active'выполняется долго, причина может быть в том, что оптимизатор выбрал index scan вместо seq scan из-за неверной оценки селективности (устаревшая статистика).
На практике часто используют EXPLAIN ANALYZE для проверки реальной селективности против ожидаемой. Расхождение в оценках (estimated rows vs actual rows) - сигнал к обновлению статистики или пересмотру индекса.
Пример кода
Пример на Go с использованием database/sql и PostgreSQL - проверка селективности через EXPLAIN:
GOpackage mainimport ("database/sql""fmt""log"_ "github.com/lib/pq")func checkSelectivity(db *sql.DB, query string) {explainQuery := "EXPLAIN (FORMAT JSON) " + queryvar result []byteerr := db.QueryRow(explainQuery).Scan(&result)if err != nil {log.Fatal(err)}fmt.Printf("Plan for %s:\n%s\n", query, result)}func main() {db, err := sql.Open("postgres", "postgres://user:pass@localhost/db?sslmode=disable")if err != nil {log.Fatal(err)}defer db.Close()// Низкая селективность - full scancheckSelectivity(db, "SELECT * FROM users WHERE is_active = true")// Высокая селективность - index scancheckSelectivity(db, "SELECT * FROM users WHERE email = 'test@example.com'")}
В выводе EXPLAIN можно увидеть "Actual Rows" и "Plan Rows" - их отношение и есть фактическая селективность.
Как отвечать на собеседовании
Начни с определения и формулы. Затем объясни влияние на выбор плана запроса. Приведи конкретный пример из практики: столбец с низкой селективностью (булевый флаг) и высокой (email). Упомяни, что оптимизатор опирается на статистику, и что устаревшая статистика - частая проблема. Если спросят про индексы - свяжи селективность с выбором типа индекса и порядком колонок в составном индексе.
Держи ответ структурированным: определение → влияние на оптимизатор → практические выводы. Не углубляйся в детали реализации конкретных СУБД, если не просят.
Что проверяет интервьюер
Интервьюер оценивает:
- Понимание базового определения и формулы.
- Умение связать селективность с планом выполнения запроса.
- Понимание разницы между высокой и низкой селективностью на практике.
- Знание того, что оптимизатор использует статистику, и что она может быть устаревшей.
- Способность применить понятие к проектированию индексов.
Для junior-уровня достаточно уверенного ответа на первые три пункта. Упоминание статистики и её обновления - плюс.
Типичные ошибки
- Путаница с кардинальностью - кардинальность это количество уникальных значений, а селективность это отношение. Не смешивай.
- Утверждение, что индекс всегда ускоряет - при низкой селективности index scan может быть медленнее full scan из-за random I/O.
- Игнорирование распределения данных - селективность зависит от конкретного значения, а не только от столбца.
- Забывание про NULL - NULL не участвует в индексах (в большинстве СУБД), что влияет на оценку селективности.
- Незнание, как посмотреть фактическую селективность - без EXPLAIN ANALYZE сложно диагностировать проблемы.
> Похожие задачи по backend
Что такое негативный кэш и почему он вреден
Является ли одиночный update транзакцией
Что такое очередь с приоритетом и как она реализуется
Как определить значение при коллизии в цепочке хэш-таблицы
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью