~/VibeHandbook

Базы данных

postgresql.org

PostgreSQL

Что это

PostgreSQL — это зрелая реляционная база данных с открытым исходным кодом, которая хранит данные в типизированных таблицах с сильной поддержкой SQL, транзакций и целостности данных. Она известна корректностью, расширяемостью и богатыми возможностями вроде JSONB, полнотекстового поиска и оконных функций. Это выбор по умолчанию для большинства бэкендов приложений, которым нужны надёжные структурированные данные.

Сильные стороны

  • ACID-транзакции и сильная согласованность по умолчанию.
  • Мощный SQL: соединения, CTE, оконные функции и агрегаты.
  • Гибкие типы, включая JSONB, массивы, диапазоны и пользовательские типы.
  • Расширения вроде PostGIS (геопространственные данные) и pgvector (эмбеддинги).
  • Сильные ограничения, внешние ключи и проверочные правила обеспечивают качество данных.

Компромиссы

  • Вертикальное масштабирование лёгкое; горизонтальный шардинг требует дополнительного инструментария.
  • Требует миграций схемы по мере развития модели.
  • Тяжелее в эксплуатации, чем однофайловая база данных, для крошечных проектов.
  • Модель «соединение на клиента» требует пулера (PgBouncer) при высокой нагрузке.

Когда использовать

Обращайтесь к PostgreSQL как к варианту по умолчанию почти для любого приложения с реляционными данными, транзакциями или потребностями в отчётности: бэкенды SaaS, электронная коммерция, аналитика и всё, что выигрывает от ограничений и соединений.

Соответствие вайб-кодингу

Управляя ИИ, дайте ему сущности и их связи, а затем попросите создать нормализованную схему с первичными ключами, внешними ключами, ограничениями NOT NULL и разумными индексами. Настаивайте на параметризованных запросах (никогда не на SQL, собранном конкатенацией строк), чтобы предотвратить инъекции, и просите ИИ оборачивать многошаговые записи в транзакцию. Хороший совет: скажите ИИ также генерировать обратимый файл миграции и объяснять каждый добавляемый индекс, чтобы вы понимали компромиссы между чтением и записью до применения.

CREATE TABLE users (
  id         BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email      TEXT NOT NULL UNIQUE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE orders (
  id       BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  user_id  BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  total    NUMERIC(10,2) NOT NULL CHECK (total >= 0),
  status   TEXT NOT NULL DEFAULT 'pending'
);

CREATE INDEX idx_orders_user_id ON orders(user_id);

-- Параметризованный запрос (плейсхолдеры, а не конкатенация)
SELECT o.id, o.total
FROM orders o
WHERE o.user_id = $1 AND o.status = $2;