11 промтов для SQL и PostgreSQL: от оптимизации запросов до безопасных миграций

11 промтов для SQL и PostgreSQL: от оптимизации запросов до безопасных миграций

Работа с PostgreSQL — это не только написание запросов, но и постоянный поиск узких мест, чтение планов выполнения, проектирование индексов и безопасное изменение схемы. По данным Stack Overflow Developer Survey 2023, PostgreSQL четвёртый год подряд признаётся самой востребованной и любимой СУБД среди разработчиков. Однако даже опытные инженеры тратят часы на анализ EXPLAIN ANALYZE или переписывание сложных JOIN.

В этой подборке — 11 практических промтов, которые превращают LLM в помощника для повседневных задач с SQL. Каждый промт сопровождается примером использования и пояснением, какую задачу он решает. Все примеры синтаксиса соответствуют официальной документации PostgreSQL 16.

1. Генерация сложного запроса с CTE и оконными функциями

Задача: быстро получить работающий SQL для аналитики без ручного перебора синтаксиса.

Промт:

Ты — эксперт по PostgreSQL 16. Напиши запрос, который для таблицы orders (поля: order_id, customer_id, order_date, total_amount, status) вычисляет для каждого клиента:
- общую сумму заказов за последние 90 дней,
- ранг клиента по этой сумме внутри его страны (поле country в таблице customers),
- разницу между текущим заказом и предыдущим по дате.
Используй CTE и оконные функции. Добавь комментарии к каждому шагу. Верни только SQL.

Пример использования: вы получаете готовый запрос с WITH recent_orders AS (...), SUM() OVER (PARTITION BY ...), LAG() OVER (ORDER BY ...). Останется только подставить свои имена таблиц. Экономия времени — от 30 минут до нескольких часов.

2. Чтение и интерпретация EXPLAIN ANALYZE

Задача: понять, почему запрос выполняется 4 секунды вместо 50 мс.

Промт:

Вот вывод EXPLAIN (ANALYZE, BUFFERS) для запроса. Объясни простыми словами, какие операции самые дорогие, где происходит Seq Scan вместо Index Scan, и предложи 3 конкретных шага по оптимизации. Укажи, какие индексы могут помочь.
<вставьте план>

Пример использования: вы копируете план, где видите Seq Scan on orders (cost=0.00..43120.00 rows=1000000 width=...)(actual time=... rows=...). LLM подскажет, что не хватает индекса по полю фильтрации, и покажет команду CREATE INDEX CONCURRENTLY. Это быстрее, чем гуглить каждую ноду плана.

3. Поиск недостающих индексов

Задача: выявить запросы, которые выиграют от нового индекса, и не создать лишних.

Промт:

Проанализируй следующие 5 SQL-запросов. Для каждого определи, по каким полям нужен индекс, какой тип (B-tree, GIN, GiST) и почему. Учти, что таблицы большие (миллионы строк), а запросы выполняются часто. Предложи составные индексы и порядок колонок. Оформи в виде таблицы.
<запросы>

Пример использования: вы получаете таблицу с рекомендациями: для WHERE status = 'active' AND created_at > now() - interval '7 days' — составной индекс (status, created_at). Это помогает избежать создания неиспользуемых индексов, которые замедляют INSERT.

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

Задача: изменить схему на проде без простоя.

Промт:

Мне нужно добавить столбец NOT NULL с DEFAULT в таблицу users (10 млн строк) и создать индекс по новому столбцу. Напиши пошаговый план миграции для PostgreSQL 16, который не блокирует таблицу надолго. Используй ALTER TABLE ... ADD COLUMN с DEFAULT, CREATE INDEX CONCURRENTLY, при необходимости — батчинг. Укажи, какие блокировки возникают на каждом шаге.

Пример использования: LLM напомнит, что в PostgreSQL 11+ добавление столбца с константным DEFAULT не требует перезаписи таблицы, а CREATE INDEX CONCURRENTLY не блокирует запись. Вы получите готовый скрипт миграции и понимание рисков.

5. Написание оконных функций для аналитики

Задача: посчитать скользящее среднее, накопительный итог, разницу с предыдущей строкой.

Промт:

Объясни, как с помощью оконных функций PostgreSQL решить задачу: для каждой строки таблицы sales (sale_date, amount) вывести:
- накопительную сумму amount за всё время,
- скользящее среднее за 7 дней,
- процент от общей суммы.
Приведи готовый SQL с оконными функциями и кратко опиши, как работает каждая.

Пример использования: вы получаете запрос с SUM(amount) OVER (ORDER BY sale_date), AVG(amount) OVER (ORDER BY sale_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW), amount / SUM(amount) OVER () * 100. Это ускоряет написание аналитических отчётов.

6. Борьба с N+1 запросами в ORM

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

Промт:

У меня Django ORM. Вот код, который в цикле обращается к связанным объектам и вызывает N+1 проблему. Перепиши его с использованием select_related и prefetch_related. Покажи, какие запросы будут выполнены до и после. Объясни, когда какой метод использовать.
<код>

Пример использования: вы заменяете for order in Order.objects.all(): print(order.customer.name) на Order.objects.select_related('customer'). LLM покажет, что вместо 1001 запроса будет 1. Это классический кейс из документации Django.

7. Аудит схемы и нормализация

Задача: проверить, соответствует ли схема третьей нормальной форме, и найти избыточность.

Промт:

Вот DDL-скрипт таблиц. Проведи аудит: есть ли нарушение 3НФ, дублирование данных, потенциальные проблемы с типами (например, использование text вместо varchar с ограничением, или jsonb там, где нужна отдельная таблица). Предложи конкретные изменения с командами ALTER TABLE. Оформи как список рекомендаций.
<DDL>

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

8. Оптимизация запроса с помощью переписывания

Задача: заменить коррелированный подзапрос на JOIN, убрать SELECT *, использовать EXISTS вместо IN.

Промт:

Перепиши этот SQL-запрос для повышения производительности. Используй JOIN вместо подзапросов, замени SELECT * на явные поля, при необходимости — EXISTS вместо IN. Объясни, почему каждая замена ускорит выполнение. Приведи план EXPLAIN до и после (предположительно).
<запрос>

Пример использования: запрос с WHERE id IN (SELECT user_id FROM orders WHERE status='paid') превращается в JOIN orders o ON o.user_id = users.id AND o.status='paid'. В PostgreSQL планировщик часто сам оптимизирует IN, но JOIN даёт больше контроля.

9. Работа с JSONB: индексы и запросы

Задача: эффективно искать по полям внутри JSONB.

Промт:

У меня таблица events с колонкой data типа jsonb. Нужно часто искать по ключу data->>'user_id' и по вложенному массиву data->'tags'. Предложи структуру индексов (GIN, expression index), покажи примеры запросов и объясни, когда какой индекс использовать. Учти производительность вставки.

Пример использования: для поиска по тегам подойдёт CREATE INDEX idx_tags ON events USING GIN ((data->'tags'));, для user_id — CREATE INDEX idx_user_id ON events ((data->>'user_id'));. LLM предупредит, что GIN замедляет вставку, поэтому не стоит индексировать всё подряд.

10. Написание хранимой процедуры или функции

Задача: инкапсулировать бизнес-логику на стороне БД.

Промт:

Напиши функцию на PL/pgSQL, которая принимает user_id и возвращает сумму заказов за указанный период. Обработай случай, когда пользователь не найден. Используй SECURITY DEFINER? Объясни выбор. Добавь комментарии и пример вызова.

Пример использования: вы получаете CREATE OR REPLACE FUNCTION get_user_total(uid int, from_date date, to_date date) RETURNS numeric AS $$ ... $$ LANGUAGE plpgsql;. Это удобно для повторяющихся вычислений и уменьшает трафик между приложением и БД.

11. Генерация тестовых данных

Задача: быстро наполнить базу реалистичными данными для тестов.

Промт:

Сгенерируй SQL-скрипт для PostgreSQL, который создаёт 10 000 строк в таблице users (id serial, name text, email text, created_at timestamptz) и 50 000 строк в orders (id, user_id, amount numeric, order_date date). Используй generate_series и random(). Данные должны быть правдоподобными: имена, email, суммы в разумных пределах. Верни готовый скрипт.

Пример использования: вы получаете скрипт с `INSERT INTO users (name, email, created_at) SELECT 'User'

|| i, 'user' || i || '@example.com', now() - (random() * interval '365 days') FROM generate_series(1, 10000) AS i;`. Это позволяет быстро подготовить окружение для нагрузочного тестирования.


Эти 11 промтов покрывают основные ежедневные задачи разработчика и аналитика, работающего с PostgreSQL. Они не заменяют знание SQL, но значительно ускоряют рутину: от чтения планов до безопасных миграций. Попробуйте применить хотя бы три из них в следующем проекте — и вы заметите, как меньше времени уходит на гугление синтаксиса и больше — на архитектуру и логику. Если хотите системно прокачать навыки работы с базами данных и AI-инструментами, обратите внимание на курсы Asibiont — там есть практические модули по SQL и PostgreSQL.

← All posts

Comments