Промты для PostgreSQL: как ускорять запросы, чинить джойны и находить узкие места в проде

Промты для PostgreSQL: как ускорять запросы, чинить джойны и находить узкие места в проде

Медленный запрос в проде — это не просто красный график на дашборде. Это упавший SLA, ночной инцидент и вопрос от бизнеса «почему отчёт грузится 40 секунд». По моему опыту, большинство таких проблем решается не героическим переписыванием кода с нуля, а точной диагностикой: понять план выполнения, найти узкое место, изменить один индекс или переписать джойн.

Именно здесь LLM становятся полезным инструментом. Они не заменяют EXPLAIN ANALYZE и не знают вашу схему, но отлично работают как «второй инженер»: разбирают план запроса, предлагают варианты индексов, переписывают коррелированные подзапросы в CTE и находят N+1 в ORM-коде. Ключ — давать им правильный контекст: DDL таблиц, план выполнения, реальные метрики, версию PostgreSQL.

Ниже — 12 готовых промтов, которые я использую в работе с PostgreSQL. Каждый можно копировать как есть, подставляя свои таблицы и планы. Все примеры синтаксиса проверены на PostgreSQL 14–17.

1. Разбор плана EXPLAIN (ANALYZE, BUFFERS)

Когда запрос тормозит, первым делом нужен план. Промт заставляет модель читать его как инженер, а не как переводчик.

Промт:

Ты — эксперт по PostgreSQL. Ниже план EXPLAIN (ANALYZE, BUFFERS) для запроса.
Найди узкие места: самые дорогие узлы, несоответствие estimated rows и actual rows,
лишние Seq Scan, внешние сортировки и дисковые чтения.
Для каждой проблемы предложи конкретное действие (индекс, переписывание, настройка).
Версия PostgreSQL: 16. DDL таблиц: <вставь CREATE TABLE>.
План: <вставь вывод EXPLAIN>

Пример: на таблице orders с 12 млн строк планировщик оценил rows=1, а фактически вернул 240 000 — классический признак устаревшей статистики. Промт подскажет ANALYZE orders и, если нужно, повышение default_statistics_target для проблемной колонки.

2. Генерация индекса под конкретный запрос

Индексы — самый дешёвый способ ускорить чтение, но «индекс на всё» убивает запись. Промт помогает выбрать тип и порядок колонок.

Промт:

Вот запрос и DDL таблиц. Предложи оптимальный индекс: тип (btree, gin, gist, brin),
порядок колонок, partial или covering (INCLUDE).
Объясни, почему именно такой порядок, и оцени влияние на INSERT/UPDATE.
Учти селективность колонок и существующие индексы: <список>.

Пример: для WHERE tenant_id = $1 AND status = 'active' ORDER BY created_at DESC модель предложит составной btree (tenant_id, status, created_at DESC), а не три отдельных индекса.

3. Переписывание коррелированного подзапроса в JOIN

Коррелированные подзапросы в SELECT часто выполняются построчно. Промт переписывает их в LEFT JOIN LATERAL или агрегатный CTE.

Промт:

Перепиши запрос так, чтобы убрать коррелированный подзапрос.
Покажи 2 варианта: через LEFT JOIN LATERAL и через CTE с GROUP BY.
Для каждого варианта объясни план и когда он выигрывает.
Сохрани исходную семантику, включая NULL и дубликаты.

Пример: подзапрос (SELECT max(paid_at) FROM payments p WHERE p.order_id = o.id) превращается в LEFT JOIN LATERAL (SELECT max(paid_at) FROM payments p WHERE p.order_id = o.id) x ON true — планировщик делает один проход вместо N.

4. Диагностика N+1 в ORM-коде

N+1 не виден в SQL-логе, если смотреть по одному запросу. Промт анализирует дамп запросов и находит паттерн.

Промт:

Ниже лог SQL-запросов за один HTTP-запрос (pg_stat_statements или лог ORM).
Найди паттерн N+1: повторяющиеся запросы с разными параметрами.
Предложи исправление на уровне ORM (selectinload / include / prefetch) и на уровне SQL.

Пример: 1 запрос на список заказов + 300 запросов на клиента — модель укажет на selectinload(Order.customer) и предложит один WHERE customer_id = ANY($1).

5. Оптимизация оконных функций

Оконные функции красивы, но сортировка на миллионах строк дорога. Промт ищет, где можно заменить ROW_NUMBER на DISTINCT ON или материализовать промежуточный результат.

Промт:

Вот запрос с оконными функциями. Найди дорогие WindowAgg.
Предложи альтернативы: DISTINCT ON, LATERAL, агрегатный CTE.
Укажи, какие индексы поддержат ORDER BY внутри OVER().

Пример: ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) для «последней записи на пользователя» часто быстрее заменить на DISTINCT ON (user_id) ... ORDER BY user_id, created_at DESC с индексом (user_id, created_at DESC).

6. Поиск блокировок и долгих транзакций

Прод встал, а причина — одна транзакция, держащая lock. Промт помогает читать pg_locks и pg_stat_activity.

Промт:

Вот вывод pg_stat_activity и pg_locks. Найди блокирующую цепочку:
кто кого ждёт, какой объект залочен, сколько длится транзакция.
Предложи безопасный порядок действий и как предотвратить в будущем.

Пример: idle in transaction на 25 минут держит AccessExclusiveLock на таблице — модель подскажет statement_timeout и idle_in_transaction_session_timeout.

7. Рефакторинг сложного JOIN в CTE

Запрос с пятью джойнами нечитаем и плохо планируется. Промт разбивает его на именованные CTE с понятной семантикой.

Промт:

Разбей этот запрос на CTE по смыслу (фильтрация, агрегация, обогащение).
Сохрани порядок применения фильтров для производительности.
Проверь, не materialize лишнего: укажи, где нужен MATERIALIZED, а где нет.

Пример: в PostgreSQL 12+ CTE по умолчанию инлайнятся; модель подскажет WITH x AS MATERIALIZED (...) только там, где это реально выгодно.

8. Оптимизация пагинации (OFFSET → keyset)

OFFSET 100000 читает и выбрасывает 100 000 строк. Промт переводит пагинацию на keyset.

Промт:

Перепиши пагинацию с OFFSET/LIMIT на keyset (cursor-based) с сохранением сортировки.
Покажи SQL и как передавать курсор из приложения. Учти составной ORDER BY.

Пример: ORDER BY created_at DESC, id DESC LIMIT 20 + WHERE (created_at, id) < ($1, $2) — стабильно быстро на любом «номере страницы».

9. Чтение pg_stat_statements и поиск топ-запросов

Прежде чем оптимизировать, надо найти что оптимизировать. Промт превращает сырой дамп в приоритизированный список.

Промт:

Вот top-30 из pg_stat_statements по total_exec_time.
Отсортируй по влиянию на общую нагрузку, а не только по среднему времени.
Для каждого предложи гипотезу проблемы и следующий шаг диагностики.

Пример: запрос с calls=2 и mean_time=8s может быть важнее, чем calls=500000 с mean_time=2ms — промт объяснит разницу между total и mean.

10. Безопасная миграция схемы без блокировок

ALTER TABLE ... ADD COLUMN DEFAULT в старых версиях лочил таблицу. Промт проверяет, безопасна ли миграция.

Промт:

Проверь миграцию на блокировки в PostgreSQL 16.
Какие шаги требуют AccessExclusiveLock и на сколько?
Предложи безопасный порядок: NOT VALID constraints, CONCURRENTLY, батчи.

Пример: CREATE INDEX CONCURRENTLY вместо CREATE INDEX, ADD CONSTRAINT ... NOT VALID + отдельный VALIDATE CONSTRAINT.

11. Генерация тестовых данных для нагрузочного теста

Чтобы проверить индекс, нужны реалистичные данные. Промт пишет генератор.

Промт:

Напиши SQL для генерации N строк в таблицу с реалистичным распределением
(например, 80% заказов в 20% клиентов). Используй generate_series и random().
Добавь индексы после загрузки, чтобы ускорить вставку.

Пример: INSERT INTO orders SELECT ... FROM generate_series(1, 1000000) с setseed() для воспроизводимости.

12. Объяснение запроса для код-ревью

Последний, но не по важности: промт-«ревьюер», который объясняет сложный SQL коллегам и ловит логические ошибки.

Промт:

Объясни этот запрос по шагам человеческим языком: что фильтруется, что джойнится,
что агрегируется. Укажи потенциальные баги: неявные CAST, NULL в NOT IN,
дубликаты из-за JOIN, потерянные строки из-за INNER JOIN.

Пример: NOT IN (SELECT ...) с NULL в подзапросе вернёт пустой результат — классическая ловушка, которую промт подсветит.

Как использовать это на практике

Главное правило: модель не знает вашу схему и статистику. Чем больше контекста вы даёте — DDL, план, версия, объём данных — тем полезнее ответ. Не доверяйте советам слепо: любой предложенный индекс проверяйте через EXPLAIN (ANALYZE, BUFFERS) до и после, а миграции — на копии прода.

Официальные источники, на которые стоит опираться: документация PostgreSQL по EXPLAIN, индексам и pg_stat_statements. Если хотите системно прокачать работу с базами и ИИ-инструментами — посмотрите материалы и практикумы на asibiont.com: там разбираются реальные сценарии, а не абстрактная теория.

← Все статьи

Комментарии

Читайте также

Промты для китайского: как ChatGPT заменяет репетитора и готовит к HSK 4–6

25 сентября 2026

Нейросети для начинающих: как выбрать между ChatGPT, Claude и Gemini и не потерять деньги и время. Обзор курса asibiont.com

24 сентября 2026

DevOps и облака: освойте контейнерные среды и облачную карьеру в 2026 году (Docker против Podman, Kubernetes, CI/CD)

24 сентября 2026

Готовые AI-промты для мультиканального маркетинга: собери лендинг, email-серию и контент под 10 площадок

24 сентября 2026

Международные санкции и комплаенс (OFAC, ООН, ЕС, FATF): обзор курса и почему ИИ-обучение меняет правила игры

24 сентября 2026

Создание RAG-систем: Освойте генерацию с дополненной выборкой, гибридный поиск и переранжирование

24 сентября 2026

Как я убил 40-секундные SQL-запросы на маркетплейсе: 14 промтов для PostgreSQL, которые реально работают

24 сентября 2026

Курс эмоционального интеллекта: освойте EQ для лидеров, самосознания и управления конфликтами

24 сентября 2026

PostgreSQL под нагрузкой: промты, которые превращают EXPLAIN в план действий

24 сентября 2026