Что означает низкая селективность индекса в SQL?

Ответ

Низкая селективность индекса — это ситуация, когда индексное выражение (столбец или комбинация столбцов) содержит много повторяющихся значений. Такой индекс плохо фильтрует данные, и СУБД часто игнорирует его, выполняя полное сканирование таблицы (full table scan), что эффективнее.

Селективность рассчитывается как отношение количества уникальных значений в индексируемом столбце к общему количеству строк.

Пример низкой селективности:

-- В таблице users 1 000 000 строк
-- Поле 'gender' имеет всего 2 уникальных значения ('M', 'F')
CREATE INDEX idx_gender ON users(gender); -- Низкая селективность!

-- Запрос вернет ~500 000 строк. СУБД, скорее всего, проигнорирует индекс idx_gender.
SELECT * FROM users WHERE gender = 'M';

Примеры полей с потенциально низкой селективностью:

  • Булевы флаги (is_active, is_deleted).
  • Перечисляемые типы с малым количеством вариантов (status, type).
  • Столбцы с плохим распределением данных (например, 99% значений NULL).

Решение:

  • Индексировать высокоселективные столбцы (например, email, uuid).
  • Использовать составные индексы, где первый столбец высокоселективен.
  • Рассмотреть частичные (условные) индексы, если фильтр применяется к подмножеству данных.
    -- Создать индекс только для активных пользователей
    CREATE INDEX idx_active_users ON users(id) WHERE is_active = true;

Ответ 18+ 🔞

Да ты посмотри, что творят-то! Сидит админ, пыхтит, индексы налево-направо строчит, а потом орет: «Почему запросы, блядь, тормозят?!» А причина-то проще пареной репы — низкая селективность индекса, ёпта!

Это когда ты, например, на столбец gender индекс повесил, а там значений-то всего два: «М» и «Ж». Ну и нахуя такой индекс, спрашивается? Он нихуя не отфильтрует, СУБД на него посмотрит, плюнет и пойдет всю таблицу сканировать, потому что так быстрее, блядь!

Селективность — это, грубо говоря, отношение уникальных значений ко всем строкам. Чем ближе к единице — тем лучше, а если там хуй с горы, то и индекс — манда с ушами.

Вот тебе наглядный пиздец:

-- Допустим, у нас миллион пользователей
-- А полов всего два, Карл!
CREATE INDEX idx_gender ON users(gender); -- Вот это, блядь, классика низкой селективности!

-- Этот запрос вытащит тебе полтаблицы, ~500к строк!
-- Оптимизатор такой: «Да похуй на твой индекс, буду всё сканировать».
SELECT * FROM users WHERE gender = 'M';

Какие поля обычно страдают этим говном?

  • Булевы флаги типа is_deleted или is_active — там нихуя не отфильтруешь.
  • Различные статусы, если их видов — раз-два и обчёлся.
  • Столбцы, где 99% значений — NULL, а остальное — пыль.

Что делать, чтобы не облажаться?

  • Индексируй то, что реально уникальноemail, uuid, primary key. Вот это — овердохуища селективность!
  • Используй составные индексы, но на первое место ставь самый селективный столбец.
  • Частичные индексы — вот это хитрая жопа! Индексируй только то, что нужно.
    -- Например, индекс только для активных юзеров — и дешево, и сердито.
    CREATE INDEX idx_active_users ON users(id) WHERE is_active = true;

Короче, думай головой, когда индексы создаёшь, а не тыкай их куда попало, как мартышлюшка!