Совет дня №5
Если в запросе одно из условий – константа, это хороший кандидат на оптимизацию.
Предположим, у нас магазин, и нужно выбрать текущие заказы пользователя. Это примерно такой запрос:
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 раз – без преувеличений.
Общее правило такое: всякие статусы, категории, флаг удаления и все прочее, что задается константой – кандидаты на выделенный индекс. Если каждый раз выбираются только активные пользователи, только текущие заказы, только не удаленные заявки – подумайте об условном индексе.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter