15 промтов для написания SQL-запросов и оптимизации БД: от новичка до эксперта

Введение

SQL (Structured Query Language) остаётся одним из самых востребованных языков в IT, даже в 2026 году, когда AI-ассистенты стали частью повседневной работы разработчиков. По данным опроса Stack Overflow за 2025 год, SQL входит в топ-5 языков по использованию, и 65% респондентов отмечают, что пишут SQL-запросы хотя бы раз в неделю. Однако, как показывает практика, большинство проблем с производительностью баз данных связано не с плохим кодом, а с неоптимальными запросами, которые генерируют даже опытные программисты.

В этой статье я собрал 15 промтов для AI-моделей (от ChatGPT до Claude и Gemini), которые помогут вам не просто написать работающий запрос, но и оптимизировать его, понять планы выполнения, избежать типовых ошибок. Каждый промт — это конкретная задача с примером результата. Подборка разбита на три уровня: базовый (для тех, кто только знакомится с SQL), продвинутый (для ежедневных задач) и экспертный (для глубокой оптимизации и администрирования).

Все примеры основаны на стандартной схеме employees (таблицы orders, customers, products), чтобы вы могли легко протестировать их у себя. Поехали!

Базовые промты: для начинающих

1. Генерация запроса по описанию задачи

Задача: Преобразовать бизнес-требование в корректный SQL-запрос без знания синтаксиса.

Промт: «Напиши SQL-запрос к таблице orders, который покажет общую сумму заказов для каждого клиента за последний месяц. Таблица содержит поля: customer_id, order_date, amount. Используй GROUP BY и HAVING.»

Пример результата:

SELECT customer_id, SUM(amount) AS total_amount
FROM orders
WHERE order_date >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '1 month')
  AND order_date < DATE_TRUNC('month', CURRENT_DATE)
GROUP BY customer_id
HAVING SUM(amount) > 0
ORDER BY total_amount DESC;

Этот запрос использует оконную функцию для группировки и фильтрации по дате. Для новичка важно, что AI объясняет каждую строку — вы можете попросить добавить комментарии.

2. Исправление синтаксической ошибки

Задача: Найти и исправить ошибку в неработающем запросе.

Промт: «Вот мой SQL-запрос: „SELECT * FROM orders WHERE order_date = ’2026-07-13’“. Он выдаёт ошибку. Исправь его и объясни причину.»

Пример результата: AI скажет, что кавычки должны быть одинарными, а не фигурными, и предложит: SELECT * FROM orders WHERE order_date = '2026-07-13'; — если поле типа date, то лучше использовать = '2026-07-13'::date.

3. JOIN для объединения таблиц

Задача: Объединить данные из двух таблиц без потери строк.

Промт: «Напиши LEFT JOIN для таблиц customers (id, name) и orders (customer_id, amount). Выведи всех клиентов, даже если у них нет заказов. Для клиентов без заказов покажи 0.»

Пример результата:

SELECT c.id, c.name, COALESCE(SUM(o.amount), 0) AS total_orders
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.id, c.name;

COALESCE — стандартная функция для замены NULL на 0.

Продвинутые промты: для ежедневной работы

4. Оптимизация медленного запроса

Задача: Ускорить запрос, который выполняется более 10 секунд на таблице с 5 миллионами строк.

Промт: «У меня есть запрос: SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE city = ’New York’). Он выполняется 12 секунд. Предложи оптимизацию с EXPLAIN ANALYZE и индексами.»

Пример результата: AI предложит заменить IN на JOIN и добавить индекс:

CREATE INDEX idx_customers_city ON customers(city);
CREATE INDEX idx_orders_customer_id ON orders(customer_id);

SELECT o.*
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE c.city = 'New York';

Согласно документации PostgreSQL, JOIN часто эффективнее подзапроса с IN, потому что планировщик может использовать hash join или merge join вместо последовательного сканирования.

5. Объяснение плана выполнения

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

Промт: «Вот результат EXPLAIN ANALYZE для моего запроса: [вставьте план]. Объясни, что означает каждая строка, и укажи, где bottleneck. Предложи исправления.»

Пример результата: AI покажет, что Seq Scan on orders (cost=0.00..45000.00 rows=1000000 width=100) — это полное сканирование таблицы из-за отсутствия индекса на order_date. Рекомендация: создать индекс CREATE INDEX idx_orders_date ON orders(order_date);.

6. Использование оконных функций для аналитики

Задача: Получить скользящее среднее или ранг без подзапросов.

Промт: «Напиши запрос, который для каждого заказа покажет его ранг по сумме внутри месяца, используя ROW_NUMBER. Таблица: orders (id, customer_id, amount, order_date).»

Пример результата:

SELECT id, customer_id, amount, order_date,
       ROW_NUMBER() OVER (PARTITION BY DATE_TRUNC('month', order_date) ORDER BY amount DESC) AS rank_in_month
FROM orders;

Оконные функции — мощный инструмент, но их неправильное использование может привести к переполнению памяти. AI подскажет, что если таблица очень большая, стоит добавить ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW для оконных агрегатов.

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

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

Промт: «Сгенерируй SQL-скрипт для вставки 1000 случайных заказов в таблицу orders. Используй GENERATE_SERIES и random().»

Пример результата:

INSERT INTO orders (customer_id, amount, order_date)
SELECT
    (random() * 100)::int + 1,
    (random() * 1000)::numeric(10,2),
    CURRENT_DATE - (random() * 365)::int
FROM generate_series(1, 1000);

Этот скрипт создаёт 1000 записей с клиентами от 1 до 100, случайными суммами и датами за последний год.

Экспертные промты: для глубокой оптимизации и администрирования

8. Анализ фрагментации индексов

Задача: Проверить, какие индексы нуждаются в реиндексации.

Промт: «Напиши запрос для PostgreSQL, который покажет степень фрагментации всех индексов в схеме public. Отфильтруй только те, где фрагментация > 30%.»

Пример результата:

SELECT
    schemaname,
    tablename,
    indexname,
    round(100 * pg_stat_user_indexes.idx_scan / NULLIF(pg_stat_user_indexes.idx_tup_read, 0), 2) AS index_usage_pct,
    pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'public'
  AND pg_stat_user_indexes.idx_scan IS NOT NULL
  AND pg_stat_user_indexes.idx_tup_read > 0
HAVING index_usage_pct < 10;

Этот запрос показывает индексы, которые редко используются. Согласно документации PostgreSQL, такие индексы стоит удалить или перестроить.

9. Оптимизация запроса с помощью материализованных представлений

Задача: Ускорить сложный агрегирующий запрос, который выполняется каждые 5 минут.

Промт: «У меня есть запрос: SELECT customer_id, COUNT(*), SUM(amount) FROM orders GROUP BY customer_id. Он выполняется 15 секунд. Предложи использовать материализованное представление с обновлением по расписанию.»

Пример результата:

CREATE MATERIALIZED VIEW mv_customer_summary AS
SELECT customer_id, COUNT(*) AS order_count, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id;

-- Обновление раз в 10 минут
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_customer_summary;

Материализованные представления хранят результат запроса физически. Время выполнения сокращается до миллисекунд, но требует места на диске.

10. Использование CTE для рекурсивных запросов

Задача: Построить иерархию подчинённых в таблице employees.

Промт: «Таблица employees содержит id, name, manager_id. Напиши рекурсивный CTE для вывода всех подчинённых конкретного менеджера (id=1).»

Пример результата:

WITH RECURSIVE subordinate_tree AS (
    SELECT id, name, manager_id, 1 AS level
    FROM employees
    WHERE id = 1
    UNION ALL
    SELECT e.id, e.name, e.manager_id, st.level + 1
    FROM employees e
    JOIN subordinate_tree st ON e.manager_id = st.id
)
SELECT * FROM subordinate_tree ORDER BY level, name;

Рекурсивные CTE — мощный инструмент, но важно настроить лимит глубины, чтобы избежать бесконечного цикла.

11. Партиционирование таблиц

Задача: Оптимизировать запросы к таблице orders с миллиардами записей.

Промт: «Таблица orders содержит 2 миллиарда записей. Запросы по дате выполняются минуты. Предложи схему партиционирования по месяцам и напиши DDL.»

Пример результата:

CREATE TABLE orders (
    id BIGSERIAL,
    customer_id INT,
    amount DECIMAL,
    order_date DATE
) PARTITION BY RANGE (order_date);

CREATE TABLE orders_2026_07 PARTITION OF orders
    FOR VALUES FROM ('2026-07-01') TO ('2026-08-01');
-- и так для каждого месяца

Партиционирование позволяет планировщику PostgreSQL сканировать только нужные разделы, сокращая время запроса с минут до секунд.

12. Диагностика блокировок

Задача: Найти и устранить взаимные блокировки (deadlocks).

Промт: «Напиши запрос для PostgreSQL, который покажет все активные блокировки с информацией о заблокированном и блокирующем процессе.»

Пример результата:

SELECT
    blocked_locks.pid AS blocked_pid,
    blocked_activity.usename AS blocked_user,
    blocking_locks.pid AS blocking_pid,
    blocking_activity.usename AS blocking_user,
    blocked_activity.query AS blocked_statement,
    blocking_activity.query AS blocking_statement
FROM pg_locks blocked_locks
JOIN pg_stat_activity blocked_activity ON blocked_locks.pid = blocked_activity.pid
JOIN pg_locks blocking_locks ON blocked_locks.locktype = blocking_locks.locktype
    AND blocked_locks.database IS NOT DISTINCT FROM blocking_locks.database
    AND blocked_locks.relation IS NOT DISTINCT FROM blocking_locks.relation
    AND blocked_locks.page IS NOT DISTINCT FROM blocking_locks.page
    AND blocked_locks.tuple IS NOT DISTINCT FROM blocking_locks.tuple
    AND blocked_locks.virtualxid IS NOT DISTINCT FROM blocking_locks.virtualxid
    AND blocked_locks.transactionid IS NOT DISTINCT FROM blocking_locks.transactionid
    AND blocked_locks.classid IS NOT DISTINCT FROM blocking_locks.classid
    AND blocked_locks.objid IS NOT DISTINCT FROM blocking_locks.objid
    AND blocked_locks.objsubid IS NOT DISTINCT FROM blocking_locks.objsubid
    AND blocked_locks.pid != blocking_locks.pid
JOIN pg_stat_activity blocking_activity ON blocking_locks.pid = blocking_activity.pid
WHERE NOT blocked_locks.granted;

Этот запрос из официальной документации PostgreSQL помогает быстро локализовать проблему.

13. Использование JSON-функций

Задача: Извлечь данные из JSON-поля без нормализации схемы.

Промт: «Таблица events содержит поле metadata типа JSONB. Напиши запрос, который извлечёт все события, где metadata->>'source' = 'web', и выведет вложенное поле user_agent.»

Пример результата:

SELECT id, metadata->>'user_agent' AS user_agent
FROM events
WHERE metadata @> '{"source": "web"}'::jsonb;

Использование @> (contains) быстрее, чем ->> для фильтрации.

14. Оптимизация с помощью индексов GIN для полнотекстового поиска

Задача: Реализовать быстрый поиск по текстовому полю.

Промт: «Таблица products содержит поле description (TEXT). Напиши запрос для поиска по нескольким словам с ранжированием по релевантности, используя GIN-индекс.»

Пример результата:

CREATE INDEX idx_products_fts ON products USING GIN(to_tsvector('english', description));

SELECT id, name, ts_rank(to_tsvector('english', description), plainto_tsquery('laptop gaming')) AS rank
FROM products
WHERE to_tsvector('english', description) @@ plainto_tsquery('laptop gaming')
ORDER BY rank DESC LIMIT 10;

GIN-индексы ускоряют полнотекстовый поиск в десятки раз.

15. Генерация отчёта по использованию ресурсов БД

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

Промт: «Напиши запрос для pg_stat_statements, который покажет топ-10 запросов по общему времени выполнения с планом.»

Пример результата:

SELECT query, total_time, calls, mean_time, rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;

Расширение pg_stat_statements должно быть включено (shared_preload_libraries). Это стандартный инструмент для мониторинга производительности.

Заключение

Промты — это не замена знаниям, а мощный инструмент для ускорения работы. Я показал 15 сценариев, от базовой генерации до экспертной диагностики блокировок и партиционирования. Главный совет: всегда проверяйте сгенерированный код на тестовой среде, особенно если запрос модифицирует данные. По данным исследования Redgate (2025), 40% разработчиков хотя бы раз сталкивались с потерей данных из-за неверно сгенерированного SQL.

Для углублённого изучения рекомендую официальную документацию PostgreSQL (postgresql.org/docs) и книгу «SQL Performance Explained» Маркуса Виннанда. А если хотите попрактиковаться в написании сложных запросов с реальными данными — создайте тестовую БД и прогоните примеры из статьи. Удачи в оптимизации!

← Все статьи

Комментарии

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

Интеграция Banana Pi с AI-агентом ASI Biont: автоматизация на одноплатнике без единой строки кода

14 июля 2026

Telegram Bot Development: как автоматизировать бизнес и заработать на ботах в 2026 году

14 июля 2026

AI-агент оживляет завод: интеграция Modbus RTU (RS-485) с ASI Biont для предиктивного обслуживания

14 июля 2026

Uber не хочет быть «всем для всех»: что на самом деле сказал продакт-директор про отели, роботакси и будущее платформы

14 июля 2026

Курс «Промышленный интернет вещей (IIoT) и системы SCADA»: ваш путь к Индустрии 4.0 в 2026 году

14 июля 2026

ИИ незаметно меняет мнения пользователей в соцсетях: как алгоритмы формируют нашу реальность

14 июля 2026

CKA + CKAD — Kubernetes Administrator & Developer: как подготовиться к сертификации в 2026 году с AI-тьютором

14 июля 2026

Как перестать терять сделки из-за языка: обзор курса «Английский для бизнеса» на asibiont.com

14 июля 2026

Трансформационное лидерство и стратегическое мышление CEO: Программа для основателей на уровне Гарварда, желающих овладеть принятием решений

14 июля 2026