Есть ли смысл ставить индексы на enum или boolean поля
Что проверяют
Понимаете ли вы селективность и то, как планировщик решает, брать индекс или нет. Правильный ответ «зависит», и интервьюер ждёт конкретных условий. Следом часто просят придумать индекс для очереди задач со статусом.
Как отвечать
Индекс выгоден, когда запрос выбирает малую долю строк. У boolean два значения, у enum единицы, поэтому всё решает распределение:
- ровное распределение: при 50 на 50 запрос
WHERE active = trueчитает полтаблицы, и последовательный скан дешевле случайных чтений по индексу. Такой индекс только замедляет запись; - редкое значение при перекосе:
status = 'FAILED'у 0,1% строк. Индекс работает, планировщик видит перекос по статистике (pg_stats.most_common_vals), еслиANALYZEне отстаёт; - частичный индекс в PostgreSQL:
CREATE INDEX ON tasks (created_at) WHERE status = 'NEW'хранит только нужные строки, занимает мало места и сразу даёт сортировку; - составной индекс: поле с малым числом значений как часть ключа, например
(status, created_at)для запроса «первые 100 новых задач по порядку». С сортировкой иLIMITон работает отлично; - bitmap-индексы Oracle: придуманы для малой кардинальности, но это инструмент аналитики, в OLTP с конкурентной записью они дают блокировки.
Для Java-стека уточните: @Index в @Table описывает только обычный индекс, частичный Hibernate не создаст, его пишут в миграции Flyway или Liquibase. Enum храните через @Enumerated(EnumType.STRING), а не ORDINAL: новая константа в середине enum тихо сломает данные.
Где спотыкаются
Говорят, что малое число значений делает индекс эффективнее. Всё наоборот: чем меньше уникальных значений, тем больше строк на каждое и тем реже индекс полезен.
Отвечают категорично «на boolean индекс не нужен никогда». Частичный индекс по редкому значению часто самый выгодный на всей таблице.
Проверяют гипотезу на пустой локальной базе. На десяти строках планировщик всегда выберет скан, смотреть надо EXPLAIN ANALYZE на объёме и распределении, близких к продакшену.