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.
Comments