🧠 Что это
Этот skill — шпаргалка по лучшим практикам PostgreSQL, ориентированная на разработчиков, которые используют Supabase или просто хотят писать эффективные и безопасные запросы. Он не заменяет полноценного ревью базы данных (для этого есть database-reviewer), а даёт быстрые ответы на типовые вопросы: какой индекс выбрать, как спроектировать схему, как настроить RLS и connection pooling. Всё основано на реальных паттернах из экосистемы Supabase.
⚙️ Как работает
📇 Индексы: когда и какой
Skill предлагает таблицу соответствия между типом запроса и оптимальным индексом:
WHERE col = value → B-tree (по умолчанию)
WHERE col > value → B-tree
WHERE a = x AND b > y → Composite (составной)
WHERE jsonb @> '{}' → GIN (для JSONB)
WHERE tsv @@ query → GIN (для полнотекстового поиска)
- Диапазоны временных рядов → BRIN (экономит место)
🧱 Типы данных: что выбрать
Короткая памятка по выбору типа:
- ID:
bigint (не int, не случайный UUID)
- Строки:
text (не varchar(255))
- Время:
timestamptz (не timestamp)
- Деньги:
numeric(10,2) (не float)
- Флаги:
boolean (не varchar или int)
🔁 Популярные паттерны
Составной индекс
CREATE INDEX idx ON orders (status, created_at);
-- Работает для: WHERE status = 'pending' AND created_at > '2024-01-01'
Правило: сначала столбцы с равенством, потом с диапазоном.
Covering Index (покрывающий)
CREATE INDEX idx ON users (email) INCLUDE (name, created_at);
-- SELECT email, name, created_at — без обращения к таблице
Partial Index (частичный)
CREATE INDEX idx ON users (email) WHERE deleted_at IS NULL;
-- Меньше размер, только активные пользователи
RLS Policy (оптимизированный)
CREATE POLICY policy ON orders
USING ((SELECT auth.uid()) = user_id);
Важно: оборачивать SELECT в скобки — иначе может быть неэффективно.
UPSERT
INSERT INTO settings (user_id, key, value)
VALUES (123, 'theme', 'dark')
ON CONFLICT (user_id, key)
DO UPDATE SET value = EXCLUDED.value;
Пагинация через курсор (Cursor Pagination)
SELECT * FROM products
WHERE id > $last_id
ORDER BY id
LIMIT 20;
-- O(1) против O(n) у OFFSET
Очередь задач (Job Queue)
UPDATE jobs SET status = 'processing'
WHERE id = (
SELECT id FROM jobs
WHERE status = 'pending'
ORDER BY created_at
LIMIT 1
FOR UPDATE SKIP LOCKED
) RETURNING *;
🚫 Анти-паттерны: как их найти
Skill содержит три полезных запроса для диагностики:
- Поиск нендексированных внешних ключей — через
pg_constraint и pg_index.
- Медленные запросы — через
pg_stat_statements (среднее время > 100 мс).
- Раздувание таблиц (bloat) — через
pg_stat_user_tables (мёртвые кортежи > 1000).
🔧 Конфигурация: шаблон
ALTER SYSTEM SET max_connections = 100;
ALTER SYSTEM SET work_mem = '8MB';
ALTER SYSTEM SET idle_in_transaction_session_timeout = '30s';
ALTER SYSTEM SET statement_timeout = '30s';
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
REVOKE ALL ON SCHEMA public FROM public;
SELECT pg_reload_conf();
🎯 Когда использовать
- При написании SQL-запросов или миграций — чтобы сразу выбрать правильный индекс и тип данных.
- При проектировании схемы — чтобы избежать типовых ошибок (например,
varchar(255) вместо text).
- При отладке медленных запросов — диагностические запросы помогут найти проблему.
- При настройке Row Level Security — оптимизированный паттерн для Supabase.
- При настройке connection pooling — шаблон конфигурации с таймаутами и лимитами.
⚠️ Важно знать
- Skill не заменяет полноценный аудит базы данных — для этого используйте
database-reviewer.
- Все паттерны проверены на практике в Supabase, но подходят для любого PostgreSQL.
- Для работы диагностических запросов может потребоваться расширение
pg_stat_statements.
- При настройке
work_mem учитывайте доступную RAM: max_connections * work_mem не должно превышать ~25% памяти.
Комментарии
Комментариев пока нет. Будьте первым.