Представьте: вы разработчик в небольшом стартапе. В штате нет DBA, а база уже тормозит. Или вы аналитик, которому нужно быстро построить отчёт, но запрос выполняется 40 секунд. Или вы бэкендер, который добавил новый индекс, а продакшн вдруг начал отвечать 500-ми. Знакомо?
По данным Stack Overflow Developer Survey 2024, PostgreSQL и MongoDB входят в топ-5 самых используемых баз данных, а Redis — в топ-10. При этом большинство команд разработки не имеют выделенного администратора баз данных. Это значит, что ответственность за производительность, индексы и миграции ложится на самих разработчиков.
В этой подборке — 12 промтов, которые превращают LLM в персонального консультанта по базам данных. Каждый промт проверен на реальных задачах: от анализа медленных запросов до настройки кеширования в Redis. Вы получите готовые формулировки, примеры входа/выхода и пояснения, почему это работает.
1. Диагностика медленного SQL-запроса через EXPLAIN ANALYZE
Задача: Запрос выполняется 8 секунд, нужно понять причину.
Промт:
Ты — эксперт по PostgreSQL. Ниже план выполнения запроса, полученный через EXPLAIN (ANALYZE, BUFFERS). Проанализируй его: найди узкие места (Seq Scan, Nested Loop с большим числом итераций, высокий actual time), предложи конкретные шаги оптимизации. Учитывай, что версия PostgreSQL 16.
План:
<вставьте вывод EXPLAIN ANALYZE>
Запрос:
<вставьте SQL>
Пример входа:
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders JOIN users ON orders.user_id = users.id WHERE orders.created_at > '2026-01-01';
Пример выхода (сокращённо):
Seq Scan on orders (cost=0.00..18334.00 rows=1000000 width=...)
Filter: (created_at > '2026-01-01')
Rows Removed by Filter: 900000
Nested Loop (cost=... rows=...)
-> Seq Scan on users
Пояснение: Промт задаёт роль и контекст (версия PG), требует конкретики. LLM укажет на Seq Scan и предложит индекс по orders(created_at) или orders(user_id, created_at).
2. Генерация индексов с учётом селективности
Задача: Нужно создать индекс, который реально ускорит выборку, а не просто «на всякий случай».
Промт:
Проанализируй таблицу orders (100 млн строк) и частые запросы:
1. SELECT * FROM orders WHERE status = 'pending' AND created_at > now() - interval '7 days';
2. SELECT user_id, count(*) FROM orders GROUP BY user_id;
Предложи оптимальные индексы. Учти селективность столбцов, возможность использования частичных (partial) и covering индексов. Объясни, почему выбран именно такой тип (B-tree, Hash, GIN).
Пример выхода:
CREATE INDEX idx_orders_pending_created ON orders (created_at) WHERE status = 'pending';
CREATE INDEX idx_orders_user_id ON orders (user_id) INCLUDE (status, created_at);
Пояснение: LLM учтёт, что status='pending' — низкая селективность, и предложит partial index. Covering index с INCLUDE позволит избежать обращения к таблице (Index Only Scan).
3. Переписывание запроса с подзапросами на JOIN
Задача: Запрос с коррелированным подзапросом выполняется медленно.
Промт:
Перепиши запрос так, чтобы убрать коррелированный подзапрос. Используй JOIN или LATERAL. Сравни планы выполнения до и после. База: PostgreSQL 16.
Исходный запрос:
SELECT u.id, u.name, (SELECT count(*) FROM orders o WHERE o.user_id = u.id) AS order_count FROM users u;
Пример выхода:
SELECT u.id, u.name, count(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.name;
Пояснение: Коррелированный подзапрос выполняется для каждой строки. JOIN с агрегацией выполняется один раз. LLM объяснит, что при большом числе пользователей разница может быть в разы.
4. Анализ и оптимизация MongoDB-запроса
Задача: Запрос в MongoDB возвращает данные 5 секунд, хотя коллекция небольшая.
Промт:
Ты — эксперт по MongoDB 7.0. Проанализируй запрос и вывод explain('executionStats'). Найди причину медленного выполнения: COLLSCAN, неэффективный индекс, неоптимальный порядок полей в составном индексе. Предложи исправления.
Запрос:
db.products.find({ category: 'electronics', price: { $lt: 1000 } }).sort({ created_at: -1 })
Explain:
<вставьте вывод>
Пример выхода:
db.products.createIndex({ category: 1, price: 1, created_at: -1 })
Пояснение: MongoDB использует индексы слева направо. Составной индекс должен покрывать фильтр и сортировку. LLM подскажет правильный порядок полей (ESR rule: Equality, Sort, Range).
5. Схема данных для MongoDB: встраивание vs ссылки
Задача: Спроектировать коллекции для блога с комментариями.
Промт:
Спроектируй схему MongoDB для блога: посты, комментарии, лайки. Учти, что комментариев может быть много (до 10 000 на пост), а лайки считаются часто. Объясни, где использовать встраивание (embedding), а где ссылки (references). Приведи примеры документов.
Пример выхода:
// posts collection
{
_id: ObjectId,
title: String,
content: String,
author_id: ObjectId,
like_count: Number,
created_at: Date
}
// comments collection
{
_id: ObjectId,
post_id: ObjectId,
author_id: ObjectId,
text: String,
created_at: Date
}
Пояснение: LLM применит правило: встраивать, если данные читаются вместе и не растут бесконечно. Лайки лучше хранить счётчиком в посте, а комментарии — отдельной коллекцией.
6. Кеширование в Redis: стратегия и TTL
Задача: Снизить нагрузку на PostgreSQL, кешируя результаты частых запросов.
Промт:
Предложи стратегию кеширования в Redis для интернет-магазина. Какие данные кешировать (каталог, корзина, сессии), какой TTL установить, как инвалидировать кеш при обновлении товара. Используй Redis 7.2. Приведи примеры команд.
Пример выхода:
SET product:123 '{"name":"...","price":...}' EX 3600
DEL product:123 # при обновлении
Пояснение: LLM объяснит паттерн Cache-Aside, важность TTL и инвалидации. Для сессий TTL может быть 30 минут, для каталога — 1 час.
7. Оптимизация Redis: выбор структуры данных
Задача: Хранить счётчики просмотров и топ-10 товаров.
Промт:
Какие структуры данных Redis лучше использовать для: 1) счётчик просмотров товара; 2) топ-10 товаров по продажам; 3) очередь задач. Объясни выбор и приведи команды.
Пример выхода:
INCR product:123:views
ZINCRBY top_products 1 product:123
LPUSH task_queue '{"task":"..."}'
Пояснение: Для счётчиков — String с INCR, для рейтингов — Sorted Set, для очередей — List или Stream. LLM подскажет, что ZSET даёт доступ к топу за O(log N).
8. Миграция схемы PostgreSQL без блокировок
Задача: Добавить столбец в таблицу с 50 млн строк без простоя.
Промт:
Как добавить столбец `discount` в таблицу orders (50 млн строк) в PostgreSQL 16 без блокировки таблицы? Напиши последовательность DDL-команд. Учти, что столбец NOT NULL с дефолтом. Объясни, какие блокировки возникают.
Пример выхода:
ALTER TABLE orders ADD COLUMN discount numeric DEFAULT 0;
-- Затем, если нужно NOT NULL:
ALTER TABLE orders ALTER COLUMN discount SET NOT NULL;
Пояснение: В PostgreSQL 11+ добавление столбца с DEFAULT не перезаписывает таблицу, но требует кратковременной блокировки. LLM предупредит о блокировках и предложит делать в часы низкой нагрузки.
9. Поиск дубликатов и очистка данных
Задача: В таблице users есть дубликаты по email.
Промт:
Напиши SQL-запрос для PostgreSQL, который находит дубликаты по email в таблице users и удаляет все, кроме самой ранней записи (по created_at). Используй CTE. Объясни запрос.
Пример выхода:
WITH duplicates AS (
SELECT id, ROW_NUMBER() OVER (PARTITION BY email ORDER BY created_at) AS rn
FROM users
)
DELETE FROM users WHERE id IN (SELECT id FROM duplicates WHERE rn > 1);
Пояснение: LLM использует оконную функцию для нумерации дубликатов и удаляет лишние. Важно: перед DELETE сделать бэкап.
10. Мониторинг и алерты для Redis
Задача: Настроить мониторинг Redis, чтобы не пропустить переполнение памяти.
Промт:
Какие метрики Redis нужно мониторить в продакшене? Предложи набор ключевых метрик (использованная память, evicted keys, hit rate), пороговые значения для алертов и команды для их получения. Используй INFO.
Пример выхода:
INFO memory # used_memory, maxmemory
INFO stats # keyspace_hits, keyspace_misses, evicted_keys
Пояснение: LLM порекомендует следить за evicted_keys (если растёт — память кончается) и hit rate (доля попаданий). Порог hit rate ниже 80% — сигнал к пересмотру TTL.
11. Транзакции в MongoDB: когда и как
Задача: Обновить баланс пользователя и записать транзакцию атомарно.
Промт:
Покажи пример транзакции в MongoDB 7.0 для перевода средств между счетами. Объясни, когда нужны транзакции, а когда можно обойтись атомарными операциями. Учти, что транзакции работают только в replica set.
Пример выхода:
const session = db.getMongo().startSession();
session.startTransaction();
try {
db.accounts.updateOne({ _id: from }, { $inc: { balance: -100 } }, { session });
db.accounts.updateOne({ _id: to }, { $inc: { balance: 100 } }, { session });
session.commitTransaction();
} catch (e) {
session.abortTransaction();
}
Пояснение: LLM напомнит, что транзакции в MongoDB имеют overhead и не всегда нужны. Для одного документа достаточно атомарных операторов.
12. План миграции с SQL на NoSQL (или наоборот)
Задача: Перейти с PostgreSQL на MongoDB для гибкой схемы.
Промт:
Мы хотим мигрировать данные из PostgreSQL в MongoDB. Таблицы: users, orders, products. Предложи стратегию миграции: как преобразовать реляционные связи в документы, как обеспечить целостность, как валидировать данные после миграции. Приведи примеры скриптов.
Пример выхода:
// Пример документа orders с встроенными product_info
{
_id: ObjectId,
user_id: ObjectId,
items: [{ product_id: ObjectId, name: String, price: Number }],
total: Number
}
Пояснение: LLM предложит денормализацию, но предупредит о рисках дублирования данных и необходимости обновлять встроенные документы при изменении товара.
Все 12 промтов объединяет одно: они дают LLM конкретный контекст (версия БД, схема, план выполнения) и требуют проверяемого результата. Это не заменяет DBA, но позволяет разработчику самостоятельно решать 80% типовых задач. Главное — всегда проверяйте предложенные индексы и миграции на тестовой среде.
Если хотите глубже разобраться в базах данных и AI-инструментах, посмотрите другие материалы на asibiont.com — там есть подборки по Python, DevOps и промпт-инжинирингу. А если у вас есть свой любимый промт для работы с БД — поделитесь в комментариях.
Comments