Прошлый вторник начался с того, что дашборд отчётов грузился 14 секунд, а ночной ETL-джоб в PostgreSQL падал по таймауту. К обеду я уже открывал EXPLAIN ANALYZE в третий раз, а к вечеру понял: я пишу одно и то же — то переписываю JOIN, то добавляю индекс, то мучаюсь с aggregation pipeline в MongoDB. Знакомо?
Именно тогда я решил делегировать рутину AI-агенту. Не «сгенерируй мне базу» — это бесполезно, а конкретные, узкие задачи: прочитать план запроса, найти узкое место, предложить переписывание, проверить индексы, сравнить два подхода. За один вечер я собрал набор промтов, который теперь использую ежедневно. Ниже — 12 рабочих промтов для PostgreSQL, MongoDB и общего SQL, с примерами и пояснениями.
Важный принцип: AI не заменяет DBA, но снимает 80% механической работы. Все промты подразумевают, что вы даёте агенту реальный контекст — план запроса, схему таблиц, версию СУБД. Без этого результат будет поверхностным.
1. Чтение EXPLAIN ANALYZE и поиск узкого места
Для чего: когда запрос тормозит, но непонятно почему. Промт заставляет AI интерпретировать план, а не гадать.
Промт:
Ты — эксперт по PostgreSQL 16. Вот вывод EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) для запроса:
[вставь JSON плана]
Запрос: [вставь SQL]
Схема таблиц: [DDL]
Найди top-3 узких места. Для каждого объясни: тип узла, оценочные vs фактические строки, стоимость. Предложи конкретные действия: индексы, переписывание, настройки. Не предлагай ничего без обоснования из плана.
Пример: я запустил этот промт для запроса, который делал Seq Scan по таблице orders на 12 млн строк. AI указал на расхождение estimated rows (100) и actual (1.2M) — классический признак устаревшей статистики. Решение: ANALYZE orders; и частичный индекс. Время запроса упало с 8.4 до 0.3 секунды.
2. Генерация индексов под конкретные запросы
Для чего: когда непонятно, какой индекс создать — одиночный, составной или частичный.
Промт:
Вот 5 самых частых запросов к таблице [имя]:
1. [SQL]
2. [SQL]
...
Схема: [DDL]
Объём: [N строк], распределение [колонка] — [описание]
Предложи минимальный набор индексов (не больше 3), который покроет эти запросы. Для каждого укажи: тип (B-tree, GIN, BRIN), колонки, порядок, WHERE-условие если частичный. Объясни, почему не нужны другие.
Пример: для таблицы events на 50 млн строк AI предложил BRIN по created_at вместо B-tree — потому что данные вставляются по времени и физически упорядочены. Размер индекса упал с 1.2 ГБ до 2 МБ, а сканирование по диапазону дат осталось быстрым.
3. Переписывание запроса: JOIN vs подзапрос vs CTE
Для чего: когда запрос работает, но неэффективно из-за структуры.
Промт:
Перепиши этот запрос тремя способами: (1) через JOIN, (2) через EXISTS, (3) через CTE.
Для каждого варианта предскажи план выполнения в PostgreSQL 16 и укажи, когда он выигрывает.
Запрос: [SQL]
Схема: [DDL]
Индексы: [список]
Пример: запрос с IN (SELECT ...) на 200k значений AI переписал на EXISTS — PostgreSQL перестал материализовать подзапрос. На реальных данных ускорение было примерно в 4 раза. Важно: AI объяснил, что в PostgreSQL 16 оптимизатор часто сам превращает IN в semi-join, но при определённых условиях этого не делает.
4. Диагностика блокировок и deadlock
Для чего: когда транзакции висят, а приложение падает с «deadlock detected».
Промт:
Вот лог ошибки PostgreSQL:
[текст ошибки]
Вот два запроса из разных транзакций:
T1: [SQL]
T2: [SQL]
Объясни, почему возник deadlock. Покажи порядок захвата блокировок. Предложи 2-3 способа исправления: изменение порядка операций, уровень изоляции, advisory locks.
Пример: классический случай — T1 обновляет строку A потом B, T2 — B потом A. AI предложил упорядочить обновления по первичному ключу. Это стандартная рекомендация, но AI сразу показал, в каком месте кода это сделать.
5. Оптимизация aggregation pipeline в MongoDB
Для чего: когда $lookup и $group съедают память и превышают лимит 100 МБ.
Промт:
У меня MongoDB 7.0. Вот aggregation pipeline:
[код pipeline]
Коллекции и объёмы: [описание]
Индексы: [db.collection.getIndexes()]
1. Найди стадии, которые можно перенести в начало для уменьшения данных.
2. Предложи, где добавить $match или $project.
3. Проверь, использует ли $lookup индекс на foreignField.
4. Если нужно — предложи allowDiskUse или переписывание через $unionWith.
Пример: pipeline с $lookup без индекса на foreignField выполнялся 22 секунды. После создания индекса и переноса $match в начало — 1.8 секунды. AI также напомнил, что $lookup не использует индексы автоматически, если foreignField не проиндексирован.
6. Сравнение explain в MongoDB
Для чего: понять, почему запрос не использует индекс.
Промт:
Вот вывод db.collection.find(...).explain("executionStats"):
[вставь JSON]
Запрос: [код]
Индексы: [список]
Объясни: почему выбран COLLSCAN вместо IXSCAN? Какие поля нужно добавить в индекс? Учти ESR-правило (Equality, Sort, Range) при построении составного индекса.
Пример: запрос с фильтром по status и сортировкой по created_at не использовал индекс. AI указал, что составной индекс должен быть {status: 1, created_at: -1} — сначала equality, потом sort. После создания индекс стал использоваться, время упало с 3.1 до 0.05 секунды.
7. Генерация миграций с учётом блокировок
Для чего: когда нужно добавить колонку или индекс на продакшене без простоя.
Промт:
Мне нужно [изменение] в PostgreSQL 16 на таблице [имя] (N строк, высокая нагрузка на запись).
Сгенерируй миграцию, которая не блокирует таблицу надолго.
Учти: CREATE INDEX CONCURRENTLY, ALTER TABLE ... ADD COLUMN с DEFAULT (в PG 11+ безопасно), NOT VALID constraints.
Дай пошаговый план: что делать в транзакции, что вне, как откатить.
Пример: добавление NOT NULL колонки с дефолтом на таблице 80 млн строк. AI предложил добавить колонку с DEFAULT (без перезаписи в PG 11+), затем создать constraint NOT VALID, потом VALIDATE CONSTRAINT отдельно. Это стандартный подход, но AI сразу выдал готовый SQL и порядок выполнения.
8. Аудит схемы: нормализация и типы данных
Для чего: когда схема «исторически сложилась» и хочется понять, что не так.
Промт:
Вот DDL таблиц [список]:
[DDL]
Проанализируй:
1. Где избыточность или нарушение нормальных форм?
2. Какие типы данных выбраны неудачно (например, varchar(255) для всего, numeric без precision)?
3. Где не хватает ограничений (CHECK, FK, UNIQUE)?
4. Что можно вынести в отдельные таблицы без потери производительности?
Дай конкретные ALTER-и и объясни риск каждого.
Пример: AI нашёл, что колонка price хранится как float — предложил numeric(10,2). Также указал на отсутствие FK между orders и customers, что уже приводило к «сиротам» в данных. Это не ускорило запросы, но устранило класс багов.
9. Оптимизация full-text search в PostgreSQL
Для чего: когда LIKE '%...%' тормозит, а нужен поиск по тексту.
Промт:
У меня PostgreSQL 16. Нужен поиск по полям title и description (русский + английский).
Текущий запрос: [SQL с LIKE]
Объём: [N строк]
Предложи схему с tsvector и GIN-индексом. Учти: язык, стемминг, веса полей, ранжирование ts_rank. Покажи DDL для generated column (PG 12+) и пример запроса.
Пример: замена LIKE '%keyword%' на to_tsvector('russian', title) @@ plainto_tsquery('russian', 'keyword') с GIN-индексом. На 2 млн записей поиск ускорился с 2.5 секунд до 15 мс. AI корректно указал, что для generated column нужна immutable-функция, а to_tsvector('russian', ...) с явной конфигурацией — immutable.
10. Генерация тестовых данных и бенчмарков
Для чего: чтобы проверить гипотезу до продакшена.
Промт:
Сгенерируй SQL для PostgreSQL, который создаст таблицу [схема] и заполнит её [N] строками реалистичных данных.
Распределение: [описание, например, 80% status='active'].
Затем напиши два варианта запроса [задача] и бенчмарк через pgbench или EXPLAIN (ANALYZE, BUFFERS).
Пример: я проверял, поможет ли партиционирование по месяцам. AI сгенерировал 5 млн строк с реалистичным распределением дат и два плана. Оказалось, что при текущем объёме партиционирование не даёт выигрыша — сэкономил день работы.
11. Перевод запроса между SQL и MongoDB
Для чего: при миграции или когда нужно сравнить подходы.
Промт:
Переведи этот SQL-запрос в MongoDB aggregation pipeline:
[SQL]
И наоборот, вот pipeline:
[код]
Переведи в SQL для PostgreSQL.
Для обоих случаев укажи, какие возможности теряются (например, оконные функции в MongoDB или $facet в SQL).
Пример: SQL с GROUP BY ... HAVING и оконной функцией ROW_NUMBER() AI перевёл в pipeline с $group и $setWindowFields (MongoDB 5.0+). Обратно — pipeline с $facet он честно сказал, что в SQL это эмулируется через UNION ALL с CTE, и это менее эффективно.
12. Постмортем: почему запрос деградировал со временем
Для чего: когда «раньше работало быстро, а теперь нет».
Промт:
Запрос [SQL] работал 0.2 сек, теперь 12 сек. Схема не менялась.
Данные выросли с [N1] до [N2] строк.
Вот текущий EXPLAIN ANALYZE: [JSON]
Проанализируй: что изменилось в плане из-за роста данных? Где оптимизатор ошибся в оценках? Что делать: обновить статистику, изменить индекс, переписать запрос, добавить партиционирование?
Пример: запрос с JOIN трёх таблиц. При росте данных PostgreSQL переключился с Nested Loop на Hash Join, но hash не помещался в work_mem и уходил на диск. AI предложил увеличить work_mem для этой сессии и переписать запрос так, чтобы вернуть Nested Loop с индексом. Это классический сценарий, и AI его распознал по плану.
Сравнение подходов: что даёт AI, а что — нет
| Задача | AI-агент | Ручная работа DBA |
|---|---|---|
| Чтение EXPLAIN | Быстро, но требует проверки | Точно, с опытом |
| Генерация индексов | Хорошо для типовых случаев | Учитывает всё |
| Переписывание запросов | 3-4 варианта за минуту | 1-2 варианта |
| Безопасность миграций | Напоминает про CONCURRENTLY | Полный контроль |
| Понимание бизнес-логики | Нет | Да |
Вывод: AI — это ускоритель, а не замена. Он не знает вашу нагрузку, не видит историю изменений и не несёт ответственности. Но он снимает рутину и подсказывает то, что вы могли забыть.
Что важно помнить
- Всегда давайте реальный план запроса. Без EXPLAIN ANALYZE или explain("executionStats") ответы будут общими.
- Проверяйте на тестовой среде. AI может предложить индекс, который замедлит запись.
- Указывайте версию СУБД. Синтаксис PostgreSQL 16 отличается от 12, а MongoDB 7.0 — от 4.4.
- Не доверяйте слепо цифрам. Если AI говорит «ускорит в 10 раз» — проверьте. Он не знает ваших данных.
- Читайте официальную документацию. PostgreSQL: postgresql.org/docs/current/using-explain.html. MongoDB: mongodb.com/docs/manual/core/explain/.
За тот вечер я не стал DBA, но перестал писать однотипный SQL вручную. Самое ценное — AI заставляет формулировать задачу точно: если вы не можете объяснить, что не так с запросом, никакой промт не поможет. Начните с промта №1 — EXPLAIN ANALYZE. Это самый быстрый способ увидеть, где на самом деле тормозит база.
Хотите глубже — изучайте планы запросов, читайте документацию, экспериментируйте на тестовых данных. AI-агент рядом, но решения принимаете вы.
Comments