К тренажеру
ВопросMediumdatabasesРеальный собес

Долгий SQL-запрос в Postgres

В Postgres медленно работает сложный запрос с join-ами и фильтрами. Как расследовать проблему и какие варианты исправления рассмотреть?

Короткий ответ

Нужно взять EXPLAIN ANALYZE с buffers, посмотреть фактические строки, join strategy, seq/index/bitmap scans, selectivity, сортировки и узкие места. Затем менять индексы, условия, порядок доступа, статистику или саму модель запроса.

Полный разбор

Первый шаг - не угадывать индекс, а посмотреть план: EXPLAIN (ANALYZE, BUFFERS) для реального запроса на похожих данных. В плане важны estimated vs actual rows, cost/time, join strategy, scan type, sort/hash operations, buffers read/hit и место, где реально тратится время.

Дальше проверяем selectivity условий, наличие подходящих compound/partial/expression indexes, актуальность статистики, необходимость ANALYZE, объем возвращаемых данных, плохие wildcard/ILIKE фильтры и join keys. Если фильтр вида ILIKE '%text%', обычный btree индекс не поможет; может понадобиться trigram index или другой search-подход.

Иногда правильное решение - не один индекс, а изменение query shape: предварительная фильтрация, materialized view, денормализация горячего read path, pagination, limit, кеширование или перенос full-text поиска в специализированный индекс.

Теория

Оптимизация SQL - это чтение фактического плана выполнения и устранение конкретного bottleneck-а, а не механическое добавление индексов.

Типичные ошибки

  • Смотреть только EXPLAIN без ANALYZE на реальных данных.
  • Добавлять индекс, не проверив selectivity и тип predicate-а.
  • Игнорировать расхождение estimated и actual rows.

Как отвечать на собеседовании

  • Скажи EXPLAIN ANALYZE BUFFERS и объясни, что ищешь в плане.
  • Упомяни trigram index для ILIKE и compound/partial indexes.