Databases

Postgres на пределе: как мы ускорили запросы в 40 раз

Всё началось с алерта: p95 latency дашборда вырос с 300 мс до 4 секунд. Виновник — «простой» отчётный запрос, который кто-то добавил полгода назад и все успешно забывали про него до конца квартала.

Первое правило оптимизации: не гадай, а смотри план. EXPLAIN ANALYZE показал sequential scan по 40 млн строк и функцию lower(email) в условии, из-за которой обычный индекс молча не использовался.

-- было: индекс не работает из-за функции в WHERE
WHERE lower(email) = $1
-- стало: expression-индекс
CREATE INDEX idx_users_email_lower
  ON users (lower(email));

Дальше — частичный индекс для горячих строк (status = 'active'), covering-индекс с INCLUDE и перенос агрегации в материализованное представление, обновляемое триггером.

Итог: 4.1 с → 98 мс на холодном кэше. Но главный вывод другой: без культуры чтения планов запросов любая «мелочь» в WHERE однажды станет ночным инцидентом.

Индекс, который не используется, — это просто дорогое место на диске. Проверяйте планы после каждого релиза схемы.

Комментарии 2

D
dba_olya31 июля 2026

Классика с lower(email) в WHERE 😄 Добавлю: ещё проверяйте pg_stat_user_indexes, там часто лежат мёртвые индексы.

А
Аноним2 августа 2026

40 раз — это красиво. У нас после такого же фикса p95 упал с 6с до 200мс, тимлид не поверил без скриншотов.

Оставить комментарий