Если в запросе одно из условий – константа, это хороший кандидат на оптимизацию.

Предположим, у нас магазин, и нужно выбрать текущие заказы пользователя. Это примерно такой запрос:

select * from orders
where user_id = ? and status = 'active'

Из прошлого совета мы знаем, что два индекса на user_id и status не работают. Будет использован только один, скорее всего для user_id, потому что у него высокая селективность (точность). Можно сделать составной индекс (status, user_id), и он будет быстрее обычного user_id.

Есть, однако, еще один вариант: условный индекс по user_id для активных заказов. У оператора create index на конце выражение where:

create index idx_users_user_id_active
on orders (user_id)
using btree
where status = 'active'

В чем прелесть такого индекса? Он намного меньше аналогов, потому что охватывает не всю таблицу, а ее подмножество. Если магазин появился не вчера, то большая часть заказов находится в статусе “доставлено”, и лишь малая часть активны. Эту часть и охватит индекс.

По условию status = 'active' Postgres определит, что нужно взять именно этот индекс. Фактически условие будет отброшено, потому что значения в индексе уже отфильтрованы по нему.

Скорость такого индекса ошеломительна: запрос может стать быстрее в 10–100 раз – без преувеличений.

Общее правило такое: всякие статусы, категории, флаг удаления и все прочее, что задается константой – кандидаты на выделенный индекс. Если каждый раз выбираются только активные пользователи, только текущие заказы, только не удаленные заявки – подумайте об условном индексе.