Вы когда-нибудь тратили полдня на написание запроса, который потом всё равно выполнялся 15 минут? Или получали от бизнеса задачу «дай выгрузку по клиентам с их последними заказами», а в голове всплывала каша из JOIN и подзапросов? Знакомо. SQL — язык мощный, но порой коварный: один неудачный JOIN превращает быстрый запрос в пожирателя ресурсов, а неоптимальный индекс — в причину ночных инцидентов. Хорошая новость: современные LLM (большие языковые модели) умеют писать и оптимизировать SQL ничуть не хуже опытного разработчика, если правильно сформулировать промт. В этой статье я собрал 15 проверенных промтов, которые помогут вам быстрее решать типовые задачи — от написания сложных выборок до профилирования и настройки производительности. Каждый промт снабжён примером использования и пояснением, как он работает. Погнали.
Базовые промты: уверенный старт
1. Написание запроса по описанию на естественном языке
Задача: Быстро получить рабочий SQL-запрос, не вспоминая синтаксис.
Промт:
Напиши SQL-запрос для PostgreSQL, который выводит список клиентов (таблица customers) с количеством их заказов (таблица orders) за последние 30 дней. Включи только клиентов, у которых более 5 заказов. Отсортируй по убыванию количества заказов.
Пример результата:
SELECT
c.customer_id,
c.name,
COUNT(o.order_id) AS order_count
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
WHERE o.order_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY c.customer_id, c.name
HAVING COUNT(o.order_id) > 5
ORDER BY order_count DESC;
Почему это работает: LLM понимает контекст и генерирует корректный синтаксис с учётом диалекта (PostgreSQL, MySQL и т.д.). Вы экономите время на поиск в документации и избегаете типичных ошибок вроде пропущенного GROUP BY.
2. Объяснение сложного запроса
Задача: Понять, что делает чужой (или ваш собственный, но забытый) SQL-код.
Промт:
Объясни, что делает этот SQL-запрос (MySQL). Разбей по шагам и поясни логику:
SELECT
DATE_FORMAT(o.order_date, '%Y-%m') AS month,
SUM(oi.quantity * oi.price) AS revenue
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
WHERE o.status = 'completed'
GROUP BY month
ORDER BY month;
Пример результата:
Этот запрос считает ежемесячную выручку по завершённым заказам.
1. Соединяет таблицы orders и order_items по идентификатору заказа.
2. Фильтрует только завершённые заказы.
3. Группирует по месяцу (формат YYYY-MM).
4. Суммирует произведение количества и цены для каждой позиции.
5. Сортирует по месяцу.
Почему это работает: Промт заставляет модель декомпозировать запрос, что полезно для обучения и быстрого входа в контекст.
3. Перевод запроса из одного диалекта в другой
Задача: Перенести запрос из MySQL в PostgreSQL (или наоборот) без ручного переписывания.
Промт:
Перепиши этот MySQL-запрос для PostgreSQL, учитывая различия в синтаксисе (например, LIMIT вместо LIMIT, ILIKE вместо LIKE, DATE_FORMAT вместо TO_CHAR):
SELECT * FROM users WHERE email LIKE '%@gmail.com' LIMIT 10;
Пример результата:
SELECT * FROM users WHERE email ILIKE '%@gmail.com' LIMIT 10;
Почему это работает: LLM знает особенности диалектов и автоматически адаптирует типы данных, функции и операторы.
Продвинутые промты: когда нужно больше, чем SELECT
4. Оптимизация медленного запроса
Задача: Ускорить запрос, который выполняется слишком долго.
Промт:
Вот SQL-запрос для PostgreSQL, который выполняется 12 секунд. Проанализируй возможные причины медлительности и предложи оптимизации: добавление индексов, переписывание JOIN, использование оконных функций вместо подзапросов.
SELECT
u.id,
u.name,
(SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS order_count
FROM users u
WHERE u.created_at > '2024-01-01';
Пример результата:
-- Оптимизированная версия:
SELECT
u.id,
u.name,
COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.created_at > '2024-01-01'
GROUP BY u.id, u.name;
Почему это работает: Модель видит коррелированный подзапрос и заменяет его эквивалентным JOIN, что позволяет базе данных использовать индексы и избежать N+1 запросов. Также может предложить добавить индекс на orders(user_id).
5. Генерация случайных тестовых данных
Задача: Создать набор данных для проверки гипотез или демонстрации.
Промт:
Сгенерируй SQL-скрипт для PostgreSQL, который создаст таблицу employees и заполнит её 100 строками случайных данных: id (серийный), name (имя), department (отдел из списка: IT, HR, Sales), salary (число от 30000 до 150000). Используй generate_series и random().
Пример результата:
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name TEXT,
department TEXT,
salary INTEGER
);
INSERT INTO employees (name, department, salary)
SELECT
'Employee_' || gs,
(ARRAY['IT', 'HR', 'Sales'])[floor(random() * 3 + 1)],
floor(random() * 120000 + 30000)::int
FROM generate_series(1, 100) AS gs;
Почему это работает: Модель знает встроенные функции генерации последовательностей и случайных чисел, поэтому может быстро создать правдоподобные данные для тестирования.
6. Работа с оконными функциями: ранжирование и скользящие средние
Задача: Вычислить скользящее среднее или ранг без сложных самоджойнов.
Промт:
Напиши запрос для PostgreSQL, который для каждого дня в таблице sales (поля: sale_date, revenue) вычисляет скользящее среднее за последние 7 дней (включая текущий). Используй оконную функцию.
Пример результата:
SELECT
sale_date,
revenue,
AVG(revenue) OVER (ORDER BY sale_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS moving_avg_7d
FROM sales
ORDER BY sale_date;
Почему это работает: Оконные функции — мощный инструмент, но их синтаксис легко забыть. Промт напоминает модели, как строить рамки окна, и выдаёт готовый код.
Экспертные промты: настройка производительности и анализ планов
7. Анализ плана выполнения запроса
Задача: Понять, почему запрос медленный, используя EXPLAIN.
Промт:
Вот план выполнения PostgreSQL для запроса. Проанализируй его и укажи узкие места: где происходит Seq Scan, высокий cost, большие значения rows. Предложи конкретные действия: какие индексы создать, как переписать запрос.
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE customer_id = 123;
Пример результата:
План показывает Seq Scan по таблице orders (cost=0.00..1000.00, rows=500). Это означает полное сканирование. Для ускорения создайте индекс:
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
После этого запрос будет использовать Index Scan, что сократит cost до 0.01..0.02.
Почему это работает: Модель интерпретирует вывод EXPLAIN и даёт практические рекомендации, основанные на знаниях о внутренностях СУБД.
8. Поиск и устранение блокировок
Задача: Диагностировать взаимоблокировки (deadlocks) в MySQL.
Промт:
У меня в MySQL происходят взаимоблокировки при выполнении транзакций. Как найти их причину? Напиши SQL-запросы для просмотра текущих блокировок и информацию из performance_schema.
Пример результата:
-- Показать текущие транзакции и блокировки
SELECT
trx_id,
trx_state,
trx_started,
trx_query
FROM information_schema.innodb_trx;
-- Показать блокировки
SELECT * FROM performance_schema.data_locks;
Почему это работает: Модель знает системные таблицы MySQL и предлагает стандартные методы диагностики.
9. Проектирование схемы базы данных
Задача: Спроектировать таблицы для нового приложения.
Промт:
Спроектируй схему базы данных PostgreSQL для интернет-магазина. Должны быть таблицы: products, categories, product_categories (многие-ко-многим), customers, orders, order_items. Укажи первичные и внешние ключи, типы данных, индексы для часто используемых полей (например, orders.customer_id).
Пример результата:
CREATE TABLE categories (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
price NUMERIC(10,2),
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE product_categories (
product_id INT REFERENCES products(id),
category_id INT REFERENCES categories(id),
PRIMARY KEY (product_id, category_id)
);
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(100)
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(id),
order_date TIMESTAMP DEFAULT NOW(),
status VARCHAR(20)
);
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
CREATE TABLE order_items (
order_id INT REFERENCES orders(id),
product_id INT REFERENCES products(id),
quantity INT,
price NUMERIC(10,2),
PRIMARY KEY (order_id, product_id)
);
Почему это работает: Модель следует лучшим практикам нормализации и добавляет индексы на внешние ключи.
10. Оптимизация запросов с помощью подсказок (hints)
Задача: Принудительно указать СУБД способ выполнения запроса, если оптимизатор ошибается.
Промт:
В PostgreSQL оптимизатор выбирает неэффективный план для запроса с JOIN. Как использовать подсказки (pg_hint_plan) или другие методы, чтобы заставить использовать hash join? Приведи пример.
Пример результата:
-- Установите расширение: CREATE EXTENSION pg_hint_plan;
SELECT /*+ HashJoin(a b) */ *
FROM a JOIN b ON a.id = b.a_id;
Почему это работает: Модель знает о расширении pg_hint_plan и объясняет, как его применять.
11. Работа с JSON-данными в PostgreSQL
Задача: Извлечь данные из JSONB-поля.
Промт:
В PostgreSQL есть таблица events с полем data типа JSONB. Напиши запрос, который извлекает из JSONB поле user.email и считает количество событий по дням.
Пример результата:
SELECT
DATE_TRUNC('day', created_at) AS day,
COUNT(*) AS event_count
FROM events
WHERE data->>'email' IS NOT NULL
GROUP BY day
ORDER BY day;
Почему это работает: Модель использует оператор ->> для извлечения текстового поля и DATE_TRUNC для группировки по дням.
12. Написание хранимой процедуры
Задача: Создать процедуру для автоматизации бизнес-логики.
Промт:
Создай хранимую процедуру в PostgreSQL, которая принимает customer_id и возвращает сумму всех заказов этого клиента. Используй PL/pgSQL.
Пример результата:
CREATE OR REPLACE FUNCTION get_customer_total(cust_id INTEGER)
RETURNS NUMERIC AS $$
DECLARE
total NUMERIC;
BEGIN
SELECT COALESCE(SUM(oi.quantity * oi.price), 0)
INTO total
FROM order_items oi
JOIN orders o ON oi.order_id = o.id
WHERE o.customer_id = cust_id;
RETURN total;
END;
$$ LANGUAGE plpgsql;
Почему это работает: Модель генерирует корректный PL/pgSQL-код с обработкой NULL.
13. Анализ временных рядов с помощью date_trunc и generate_series
Задача: Заполнить пропуски в датах и посчитать метрики.
Промт:
В PostgreSQL есть таблица daily_sales (sale_date date, amount numeric). Некоторые дни отсутствуют. Напиши запрос, который выводит все дни за последние 30 дней и сумму продаж (0, если нет данных). Используй generate_series.
Пример результата:
WITH dates AS (
SELECT generate_series(CURRENT_DATE - INTERVAL '29 days', CURRENT_DATE, '1 day')::date AS day
)
SELECT
d.day,
COALESCE(SUM(s.amount), 0) AS total_sales
FROM dates d
LEFT JOIN daily_sales s ON s.sale_date = d.day
GROUP BY d.day
ORDER BY d.day;
Почему это работает: Модель использует CTE и generate_series для создания непрерывного ряда дат, а LEFT JOIN для подстановки нулей.
14. Настройка пула соединений и параметров PostgreSQL
Задача: Улучшить производительность сервера БД.
Промт:
Какие основные параметры в postgresql.conf влияют на производительность? Напиши рекомендации для OLTP-нагрузки с 1000 одновременными соединениями. Укажи значения для shared_buffers, work_mem, max_connections.
Пример результата:
Для OLTP-нагрузки с 1000 соединений:
- shared_buffers: 25% от ОЗУ, но не более 8ГБ (например, 4ГБ).
- work_mem: начните с 64MB, но помните, что это на каждую сортировку.
- max_connections: 1000, но лучше использовать пулер (PgBouncer), чтобы снизить накладные расходы.
- effective_cache_size: 75% от ОЗУ.
- wal_buffers: 16MB.
Почему это работает: Модель даёт проверенные рекомендации, основанные на официальной документации PostgreSQL.
15. Анализ лога медленных запросов
Задача: Выявить проблемные запросы в MySQL.
Промт:
В MySQL включён slow_query_log. Как проанализировать этот лог, чтобы найти самые медленные запросы? Напиши команды для mysqldumpslow и примеры.
Пример результата:
Используйте утилиту mysqldumpslow:
mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log
Это выведет 10 самых медленных запросов по времени выполнения. Утилита агрегирует похожие запросы, заменяя параметры на N.
Почему это работает: Модель знает стандартные инструменты MySQL и их синтаксис.
Заключение
Эти 15 промтов — лишь вершина айсберга. Главное — понимать, что LLM — это не замена знаниям SQL, а мощный инструмент, который ускоряет рутину и помогает исследовать незнакомые области. Используйте их как отправную точку: адаптируйте под свои задачи, проверяйте результаты на реальных данных и не забывайте про EXPLAIN. Если вы хотите глубже освоить SQL и научиться писать эффективные запросы, обратите внимание на наш курс по анализу данных — там мы разбираем такие примеры в деталях. А пока — попробуйте применить хотя бы один промт из этой статьи в своей работе, и вы увидите, как экономите часы. Удачных запросов!
Комментарии