Эффективно ли индексировать булевые поля в базах данных и в каких случаях это оправдано?

Ответ

В общем случае, индексировать булевые поля неэффективно.

Основная проблема: Низкая кардинальность

Индекс работает эффективно, когда он помогает базе данных быстро отсеять большую часть строк. У булевого поля всего два возможных значения (true и false). Это называется низкой кардинальностью (или низкой селективностью).

Если значения распределены примерно 50/50 (например, поле is_active), то при поиске по WHERE is_active = true индекс в лучшем случае укажет на половину таблицы. В такой ситуации планировщик запросов СУБД (например, PostgreSQL или MySQL) скорее всего выберет полное сканирование таблицы (Full Table Scan), так как это будет быстрее, чем сначала обращаться к индексу, а затем к таблице.

Когда индексирование булевых полей оправдано?

Есть два основных случая, когда такой индекс может быть полезен:

  1. Сильно искаженное распределение данных. Если одно из значений встречается крайне редко. Например, в таблице users есть поле is_admin, и только 0.1% пользователей являются администраторами. Запрос SELECT * FROM users WHERE is_admin = true; будет очень селективным, и индекс на этом поле значительно ускорит поиск.

  2. Использование частичных (Partial) или фильтрованных (Filtered) индексов. Это наиболее правильный подход. Вы можете создать индекс только для того значения, которое вас интересует. Это делает индекс маленьким и очень быстрым.

    Пример для PostgreSQL:

    -- Индексируем только активных пользователей
    CREATE INDEX idx_users_active ON users (is_active) WHERE is_active = true;

    Такой индекс будет использоваться только для запросов вида WHERE is_active = true.

Вывод:

Избегайте стандартных индексов на булевых полях, если распределение данных близко к 50/50. Если данные сильно искажены или вам нужно часто фильтровать по одному конкретному значению — используйте частичные индексы. Всегда проверяйте план выполнения запроса с помощью EXPLAIN.

Ответ 18+ 🔞

Давай разберём этот вопрос про индексы на булевых полях, а то народ часто наступает на эти грабли, как слепой крот на вертел.

Вот представь себе, блядь, обычное поле is_active в таблице пользователей. Всего два значения: true и false. Кардинальность — хуй да маленько. Планировщик запроса смотрит на это и думает: «Ну и нахуя мне тут индекс, если по нему я отсею максимум половину таблицы?». И он прав, ёпта! Полное сканирование таблицы часто оказывается быстрее, чем прыжки: сначала в индекс, а потом по ссылкам обратно в таблицу. Всё, накрылся наш индекс медным тазом, ресурсы потрачены зря.

Но! Есть же, сука, исключения, где этот индекс выстрелит, как хитрая жопа из засады.

  1. Сильно перекошенное распределение. Допустим, у тебя поле is_banned. Забаненных — 0.1%, а нормальных пользователей — 99.9%. Вот тогда запрос «найди всех забаненных уёбков» будет охуенно селективным, и индекс на is_banned станет твоим лучшим другом. Планировщик его схавает и скажет спасибо.

  2. Частичные (Partial) индексы — вот где магия, блядь! Это самый каноничный способ работы с булевыми полями. Зачем индексировать всё подряд, если тебе нужно только одно значение? Создаёшь индекс не на всё поле, а только на интересующий тебя кусок.

    Смотри, как это выглядит в PostgreSQL:

    -- Индексируем только активных пользователей, ебать его в сраку
    CREATE INDEX idx_users_active ON users (is_active) WHERE is_active = true;

    Такой индекс — маленький, быстрый и целенаправленный, как удар вилкой в глаз. Он будет использоваться только для запросов вида WHERE is_active = true. Красота, ёперный театр!

Итог, Колян: Не лепи индекс на булево поле просто так, от скуки. Сначала посмотри на распределение данных. Если оно 50/50 — забей хуй. Если нужно ловить редкие значения — используй частичные индексы. И всегда, блядь, смотри план запроса через EXPLAIN, а не гадай на кофейной гуще.