Ответ
Низкая селективность индекса — это ситуация, когда индексное выражение (столбец или комбинация столбцов) содержит много повторяющихся значений. Такой индекс плохо фильтрует данные, и СУБД часто игнорирует его, выполняя полное сканирование таблицы (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;
Короче, думай головой, когда индексы создаёшь, а не тыкай их куда попало, как мартышлюшка!