Ответ
Условный индекс (Partial/Filtered Index) — это индекс, построенный только для подмножества строк таблицы, удовлетворяющих заданному условию WHERE. Это уменьшает размер индекса и ускоряет запросы, которые используют это же условие.
Создание в PostgreSQL:
-- Индекс только для активных заказов
CREATE INDEX idx_orders_active ON orders (customer_id, created_at)
WHERE status = 'ACTIVE';
-- Индекс для не удаленных записей
CREATE INDEX idx_users_not_deleted ON users (email)
WHERE deleted_at IS NULL;
Особенности и best practices:
- Производительность: Индекс меньше по размеру, быстрее строится и обновляется.
- Использование: Оптимизатор СУБД сможет использовать индекс только если условие в запросе логически влечет условие индекса. Например, индекс
WHERE status = 'ACTIVE'не будет использован для запросаWHERE status IN ('ACTIVE', 'PENDING'). - Поддержка СУБД:
- PostgreSQL, SQLite: Полная поддержка.
- MySQL (8.0+): Поддерживаются как Functional Indexes, которые можно использовать для той же цели.
-- Пример в MySQL 8.0 CREATE INDEX idx_status ON orders ((1)) WHERE status = 'ACTIVE'; - SQL Server: Использует Filtered Indexes.
- В JPA: Прямого создания через аннотации нет. Условные индексы создаются с помощью нативных SQL-скриптов в инструментах миграции (Flyway, Liquibase).
Ответ 18+ 🔞
А, слушай, вот это тема, про которую многие даже не в курсе, а зря! Условный индекс — это как если бы ты в огромном шкафу с одеждой завел отдельную полочку только для летних футболок. Зачем таскать с собой всё барахло, если тебе нужны только они, да?
Короче, что это такое? Это индекс, который строится не на всю таблицу, а только на часть строк, которые проходят по фильтру. Типа, «индексируем только то, что реально часто ищем». Размер меньше, скорость выше — красота, ебать мои старые костыли!
Как его слепить в PostgreSQL:
-- Допустим, тебе постоянно нужно искать активные заказы по клиенту и дате.
-- Зачем индексировать все миллионы отменённых и доставленных? Бред же!
CREATE INDEX idx_orders_active ON orders (customer_id, created_at)
WHERE status = 'ACTIVE';
-- Или классика: индексируем только живых юзеров, а удалённых — нахуй не надо.
CREATE INDEX idx_users_not_deleted ON users (email)
WHERE deleted_at IS NULL;
А теперь подводные ебучки и важные фишки:
- Выгода: Индекс легковесный, строится быстрее, меньше жрёт места на диске и при обновлении данных не так грузит систему. Овердохуища пользы!
- Главный нюанс, блядь! Оптимизатор — хитрая жопа. Он использует этот индекс только если твой запрос логически следует условию индекса. Вот пример: если у тебя индекс
WHERE status = 'ACTIVE', а ты в запросе ищешьWHERE status IN ('ACTIVE', 'PENDING')— всё, поезд ушёл, индекс проигнорируют. Он же не для пендингов, ёпта! - Где что поддерживается:
- PostgreSQL, SQLite: Тут всё чётко, полная поддержка, как в аптеке.
- MySQL (начиная с 8.0): Прямых условных индексов нет, но есть Functional Indexes, которыми можно выебать систему и добиться того же. Смотри:
-- Это типа как условный индекс в MySQL CREATE INDEX idx_status ON orders ((1)) WHERE status = 'ACTIVE'; - SQL Server: Там это называется Filtered Indexes, суть та же.
- А как в JPA/Hibernate это сделать? Да нихуя не сделать, вот в чём прикол! Стандартные аннотации этого не умеют. Придётся лезть в миграционные скрипты (Flyway, Liquibase) и там уже нативными SQL-запросчиками этот индекс и создавать. JPA тут просто разводит руками, мол, «это не моя епархия, чувак».
В общем, штука мощная, но требующая аккуратности. Как скальпель: если применять к месту — спасёт жизнь, а если тыкать куда попало — можно и пиздец натворить.