Вы когда-нибудь проводили часы за разбором медленного запроса, чтобы в итоге найти пропущенный индекс? Или пытались объяснить джуну, почему EXPLAIN ANALYZE показывает Seq Scan на таблице с миллионами строк? Если да, то вы знаете, как много времени отнимает рутинная оптимизация. Но что, если часть этой работы можно делегировать нейросети? Речь не о магии: современные языковые модели при правильной постановке задачи способны анализировать планы выполнения, предлагать индексы и даже генерировать миграции. В этой статье я собрал 12 промтов, которые сам использую в работе с PostgreSQL — от базового объяснения EXPLAIN до рефакторинга целой схемы. Никакой воды, только конкретика и примеры.
Базовые промты: когда нужно быстро разобраться в запросе
1. Объяснение плана выполнения как для новичка
Когда использовать: Вы получили от коллеги EXPLAIN ANALYZE и не понимаете, почему запрос медленный. Промт заставит модель разложить план по полочкам.
Промт:
Ты — эксперт по PostgreSQL. Объясни следующий план выполнения запроса простым языком, как для разработчика с базовым знанием SQL. Для каждого узла плана укажи: что он делает, сколько времени занимает, какие проблемы видны (например, Seq Scan на большой таблице, высокая стоимость, несоответствие строк). Предложи, что можно оптимизировать.
План:
[вставьте сюда вывод EXPLAIN ANALYZE]
Пример результата:
Модель укажет, что Seq Scan по таблице orders (100M строк) — главный тормоз, и порекомендует индекс по customer_id, так как фильтр WHERE customer_id = 123 использует этот столбец. Также заметит rows и actual rows расхождения, что указывает на устаревшую статистику.
2. Перевод медленного запроса на современный синтаксис
Когда использовать: Легаси-код с устаревшими JOIN в FROM или подзапросами, которые можно переписать на WITH или LATERAL.
Промт:
Перепиши данный SQL-запрос для PostgreSQL 15+ с использованием современных конструкций (CTE, LATERAL, оконные функции). Сохрани логику полностью. Добавь комментарии к изменениям. Вот запрос:
[ваш SQL]
Пример: Модель перепишет вложенный подзапрос в LEFT JOIN LATERAL, что улучшит читаемость и может ускорить выполнение.
3. Поиск пропущенных индексов по схеме и запросу
Когда использовать: Когда нужно быстро понять, каких индексов не хватает для конкретного запроса.
Промт:
У меня есть таблица:
[CREATE TABLE ...]
И запрос:
[SELECT ... WHERE ... ORDER BY ...]
Сравни условия WHERE, JOIN и ORDER BY со списком существующих индексов. Предложи новые индексы, которые ускорят запрос. Для каждого индекса объясни, почему он нужен и как повлияет на план. Учти селективность.
Пример: Модель предложит композитный индекс (customer_id, created_at) для запроса с фильтром по клиенту и сортировкой по дате.
Продвинутые промты: работа с планами и статистикой
4. Анализ узкого места в плане выполнения
Когда использовать: План сложный, нужно найти самый дорогой узел.
Промт:
Проанализируй этот EXPLAIN ANALYZE и найди узел с наибольшей общей стоимостью. Объясни, почему он дорогой, и предложи 2-3 варианта оптимизации (индексы, изменение JOIN, переписывание). Для каждого варианта оцени сложность и ожидаемый эффект.
[план]
Пример: Модель укажет на Hash Join, который выполняется долго из-за нехватки памяти (work_mem), и посоветует увеличить work_mem или добавить индекс для ускорения Hash.
5. Проверка на наличие анти-паттернов
Когда использовать: Код-ревью SQL.
Промт:
Проверь SQL-запрос на анти-паттерны: SELECT *, отсутствие LIMIT, неявные приведения типов, использование функций в WHERE без индекса, OR для разных столбцов, вложенные подзапросы, которые можно заменить на JOIN. Для каждого найденного паттерна объясни проблему и дай исправленный вариант.
Запрос:
[SQL]
Пример: Модель найдет WHERE date(created_at) = '2024-01-01' и предложит WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02' для использования индекса.
6. Сравнение двух вариантов запроса
Когда использовать: Сомневаетесь, какой стиль запроса лучше.
Промт:
Сравни два SQL-запроса, которые возвращают один и тот же результат. Оцени производительность, читаемость, поддерживаемость. Учти, что таблица A содержит 1M строк, таблица B — 10M. Дай рекомендацию, какой использовать и почему.
Запрос 1: ...
Запрос 2: ...
Пример: Модель сравнит NOT IN и LEFT JOIN ... IS NULL, объяснит, что NOT IN может дать неверные результаты при NULL, и порекомендует LEFT JOIN.
Экспертные промты: проектирование схем и миграции
7. Генерация миграции для изменения схемы
Когда использовать: Нужно изменить тип столбца или добавить ограничение.
Промт:
Сгенерируй SQL-миграцию для PostgreSQL. Таблица: users. Удали столбец 'legacy_field', добавь столбец 'email' с типом CITEXT и уникальным ограничением, измени тип столбца 'age' с INTEGER на SMALLINT. Оберни в транзакцию. Добавь комментарии.
Пример: Модель создаст скрипт с ALTER TABLE ... DROP COLUMN, ADD COLUMN ... UNIQUE, ALTER COLUMN ... TYPE ... USING, в BEGIN; ... COMMIT;.
8. Нормализация схемы до 3НФ
Когда использовать: У вас плоская таблица, нужно разбить.
Промт:
Приведи данную таблицу к третьей нормальной форме (3NF). Опиши, какие таблицы создашь, какие первичные и внешние ключи, какие ограничения. Учти, что PostgreSQL поддерживает CHECK, UNIQUE, FOREIGN KEY. Исходная таблица:
[CREATE TABLE ...]
Пример: Модель разделит таблицу с повторяющимися данными о клиентах на customers и orders, связав их внешним ключом.
9. Проектирование схемы для нового микросервиса
Когда использовать: Нужен черновик схемы по описанию.
Промт:
Спроектируй схему PostgreSQL для микросервиса управления заказами. Сущности: клиент, заказ, товар, оплата. Опиши таблицы, типы данных, индексы для частых запросов (поиск заказов по клиенту и дате). Добавь ограничения целостности. Учти, что заказов будет много, поэтому партиционирование по дате — плюс.
Пример: Модель предложит таблицы customers, orders (партиционированную по created_at), order_items, payments, с индексами на customer_id, created_at, status.
10. Рефакторинг схемы с сохранением данных
Когда использовать: Нужно объединить дублирующиеся таблицы.
Промт:
У меня есть две таблицы: 'clients' и 'partners' с похожей структурой. Хочу объединить в 'contacts'. Напиши миграцию, которая перенесет данные, добавит тип ('client' или 'partner'), создаст уникальный ключ на email. Сохрани данные.
Пример: Миграция с INSERT INTO contacts SELECT ..., добавлением CHECK, использованием ON CONFLICT для обработки дублей.
11. Оптимизация запросов с полнотекстовым поиском
Когда использовать: Нужно ускорить поиск по тексту.
Промт:
У меня таблица articles с колонкой body TEXT. Запрос: SELECT * FROM articles WHERE to_tsvector('russian', body) @@ plainto_tsquery('russian', 'поисковый запрос'); Он медленный. Предложи оптимизацию: создание GIN-индекса, использование поисковой колонки, альтернативы LIKE. Учти, что PostgreSQL поддерживает tsvector.
Пример: Модель предложит CREATE INDEX ... USING GIN (to_tsvector('russian', body)); и объяснит, как это ускорит поиск.
12. Генерация тестовых данных
Когда использовать: Нужно заполнить таблицу для нагрузочного теста.
Промт:
Сгенерируй SQL для вставки 1000 тестовых записей в таблицу users (id, email, created_at). Email должны быть уникальными и в формате 'userN@example.com'. created_at — случайная дата за последний год. Используй generate_series и random().
Пример: Модель предложит `INSERT INTO users (email, created_at) SELECT 'user'
|| g || '@example.com', NOW() - (random()*365 || ' days')::interval FROM generate_series(1,1000) g;`
13. Объяснение работы LATERAL на примере
Когда использовать: Когда нужно понять, как использовать LATERAL для нестандартных задач.
Промт:
Объясни, что делает LATERAL в PostgreSQL, и приведи пример, где без него сложно. Покажи запрос с LATERAL, который находит последний заказ для каждого клиента.
Пример: Модель покажет SELECT c.name, o.total FROM customers c LEFT JOIN LATERAL (SELECT total FROM orders WHERE customer_id = c.id ORDER BY created_at DESC LIMIT 1) o ON true;
14. Использование оконных функций для аналитики
Когда использовать: Нужно написать сложный отчет.
Промт:
Напиши запрос с оконной функцией для подсчета скользящего среднего за 7 дней по продажам. Таблица: sales (sale_date DATE, amount NUMERIC). Выведи дату, сумму, среднее за 7 дней.
Пример: SELECT sale_date, amount, AVG(amount) OVER (ORDER BY sale_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS moving_avg FROM sales;
15. Выявление и устранение блокировок
Когда использовать: Приложения зависают из-за блокировок.
Промт:
Дай SQL-запросы для обнаружения блокировок в PostgreSQL: pg_locks, pg_stat_activity. Объясни, что такое взаимоблокировка (deadlock) и как ее избежать. Приведи пример настройки lock_timeout.
Пример: Модель предоставит запрос с SELECT * FROM pg_stat_activity WHERE state = 'active'; и советует использовать LOCK TABLE ... IN SHARE MODE аккуратно.
16. Настройка пула соединений и параметров
Когда использовать: Оптимизация конфигурации под нагрузку.
Промт:
Какие параметры PostgreSQL стоит настроить для приложения с большим количеством одновременных соединений (например, 200)? Рассмотри max_connections, shared_buffers, work_mem. Дай рекомендуемые значения для сервера с 8GB RAM.
Пример: Модель даст ориентиры: shared_buffers=2GB, work_mem=32MB и объяснит влияние.
Что важно помнить при работе с промтами
Нейросеть — не замена экспертизе, а инструмент. Всегда проверяйте предложенные индексы на реальных данных, используйте EXPLAIN (BUFFERS, ANALYZE) для подтверждения. Промты лучше работают, когда вы даете полный контекст: версию PostgreSQL, объем таблиц, наличие индексов.
Попробуйте эти промты на своих задачах — вероятно, вы удивитесь, сколько времени они сэкономят. А если у вас есть свои проверенные формулировки, делитесь в комментариях — обмен опытом делает нас сильнее.
Комментарии