СХЕМА - логическое объединение таблиц в БД. Это просто логическая папка, в которую вы кладёте таблицы, индексы, функции и т.д.

БД - физическое объединение таблиц. База данных в кластере полностью изолирована от других (у неё свои таблицы, пользователи, привилегии и т.д.).

Блок данных = 8192 байт

PSQL-инстанс — это, как правило, экземпляр сервера PostgreSQL, то есть запущенный процесс (или набор процессов) СУБД PostgreSQL, который:

  • слушает определённый порт (по умолчанию 5432),
  • управляет одной или несколькими базами данных,
  • обслуживает подключения клиентов (например, через psql, приложения и т.д.).

Индекс - отношение, которое содержит данные, полученные из таблицы или материализованного представления. Его внутренняя структура поддерживает быстрое извлечение и доступ к исходным данным.

Это дополнительная структура, которая хранит часть данных таблицы в упорядоченном виде для быстрого поиска. B-tree, но есть и другие: GIN (для полнотекстового поиска), GiST (геоданные), BRIN (для больших упорядоченных таблиц) и т.д. Индексы не заменяют таблицу, а только ссылаются на строки в ней (обычно через CTID — координаты страница+смещение).

Табличное пространство - позволяет организовать логику размещения файлов объектов базы данных в файловой системе. Вы можете распределить таблицы по разным табличным пространствам (tablespaces) — это просто ссылки на другие каталоги на диске. Это полезно, если у вас разные диски (быстрый SSD и медленный HDD), и вы хотите разнести «горячие» и «холодные» данные.

Первичный ключ:

  • атрибуты в первичном ключе не имеют нулевых значений
  • для каждой таблицы может быть только один первичный ключ

Транзакция - комбинация команд, которые должны действовать как единая атомарная команда

Страница данных (data page) — это базовая единица хранения в PostgreSQL, представляющая собой блок размером 8 КБ, в котором хранятся строки таблиц (tuples), индексы, служебные структуры и метаданные.

“Грязные” страницы - это страницы данных в памяти (shared_buffers), которые были изменены, но ещё не записаны на диск.

WAL - Журнал транзакций, в который PostgreSQL сначала записывает описание любого изменения данных, и только потом применяет это изменение к самим данным.

WAL writer - Фоновый процесс, который асинхронно сбрасывает WAL-записи из памяти (wal_buffers) на диск (pg_wal/).

background writer - Фоновый процесс, который асинхронно сбрасывает «грязные» страницы данных (heap, индексы) из shared_buffers на диск.

LSN (Log Sequence Number) — это уникальный идентификатор позиции в WAL (Write-Ahead Log). Он показывает, до какой точки из WAL-логов уже применены изменения на этом сервере. Формат: X/Y, где:

  • X — номер сегмента WAL (в шестнадцатеричном виде),
  • Y — смещение внутри этого сегмента (тоже в hex).
  • Если LSN на standby отстаёт — это нормально (репликация асинхронная).
  • Если LSN не меняется со временем — репликация остановилась.
  • Если LSN совпадает или почти совпадает — репликация работает ✅.

MVCC - Многоверсионное управление конкурентным доступом (Никогда не перезаписывай данные на месте. Всегда создавай новую версию строки)

Autovacuum - автоматически запускаемый механизм ри выполнении условия заданный формулой (см. Autovacuum)

tuple - запись/строка

Plain SQL-файл («обычный SQL-файл») — это текстовый файл, содержащий последовательность SQL-команд, которые можно выполнить в СУБД (в данном случае — PostgreSQL), чтобы воссоздать структуру базы данных и/или её данные.

Архивация WAL — это процесс копирования завершённых WAL-файлов (по 16 МБ) из каталога pg_wal/ в долговременное хранилище (диск, NFS, S3 и т.д.) сразу после их заполнения. Point-in-Time Recovery (PITR) — это механизм в PostgreSQL, который позволяет восстановить базу данных до любого момента времени в прошлом, начиная с момента создания полного резервного копирования.

major- / minor- версии

# Начиная с PostgreSQL 10, используется упрощённая схема версий:
PostgreSQL <major>.<minor>
### Примеры:
# 16.3 → major = 16, minor = 3
# 15.7 → major = 15, minor = 7
# 14.0 → major = 14, minor = 0
 
## Major-версия — это главный релиз
# Новые функции (MERGE, JSON_TABLE, параллельные индексы и т.д.),
# Изменения в формате данных (страниц, WAL, системных каталогов),
# Новые системные представления,
# Иногда — изменения в SQL-поведении.
# ❌ Нельзя просто заменить бинарники — данные не совместимы.
# ❌ Нельзя подключить standby от старой major-версии.
# ❌ Нельзя восстановить `pg_basebackup` от другой major-версии.
# - Требует миграции данных:
#   - Через `pg_dump` / `pg_restore` (логическое обновление),
#   - Или через `pg_upgrade` (физическое обновление, быстрее).
 
## Minor-версия — это патч-релиз
# Исправление багов,
# Устранение уязвимостей безопасности,
# Очень редко — минимальные улучшения производительности.
# ✅ Полная обратная совместимость на уровне данных.
# ✅ Можно просто заменить бинарники и перезапустить кластер.
# ✅ Standby от старой minor-версии работает с новым primary (и наоборот).
# ✅ `pg_basebackup` от 16.2 можно запустить как 16.3.

Subscriber (Подписчик) — это сервер PostgreSQL, который получает поток изменений данных (INSERT, UPDATE, DELETE) от одного или нескольких других серверов. Он «подписывается» на одну или несколько публикаций (publications), которые созданы на сервере-источнике (publisher).

Кластер PostgreSQL — это не кластер в привычном смысле

Кластер PostgreSQL - это один запущенный экземпляр СУБД, который управляет одним или несколькими базами данных.

PostgreSQL использует многопроцессную архитектуру (а не многопоточную).

  • Это не распределённая система, а просто одна инсталляция PostgreSQL на одном сервере (или в одном контейнере), содержащая:
    • Несколько баз данных (например: postgres, myapp_db, test_db).
    • Общие системные каталоги, журналы транзакций (WAL), процессы и т.д.

!!!

Под “кластером” не понимается несколько серверов, объединённых в кластер (это уже High Availability или репликация — отдельная тема).

Кластер — это набор процессов и файлов, работающих вместе. Он живёт в каталоге данных (PGDATA, например: /var/lib/postgresql/15/main).

Backend-процессы (серверные процессы)

  • Один процесс = одно клиентское подключение. У каждого:
    • Своя локальная память (кэш планов, временные буферы и т.д.).
    • Общий доступ к разделяемой памяти кластера (shared_buffers, wal_buffers и др.) - это часть RAM, куда PostgreSQL кэширует страницы данных с диска. Выполняет:
    • Парсинг и планирование SQL-запросов.
    • Чтение/запись данных через общий буферный кэш.
    • Взаимодействие с WAL и системными каталогами.

!!!

Клиент никогда не читает файлы напрямую — всё идёт через серверный процесс. Это важно для безопасности и целостности.

Страницы данных и отсутствие сжатия (в обычном PostgreSQL)

  • Данные хранятся в страницах (page) по 8 КБ каждая.
  • В стандартном PostgreSQL (от сообщества) данные не сжимаются на уровне страниц — они хранятся «как есть». если у вас много повторяющихся значений или длинные тексты, PostgreSQL не упакует их автоматически, чтобы сэкономить место или ускорить чтение.
Postgres Pro
коммерческая российская сборка PostgreSQL с дополнительными фичами.

Постраничное сжатие:

  • Страницы на диске хранятся в сжатом виде.

  • При чтении в память (shared_buffers) они распаковываются.

  • Вся логика работы с данными (индексы, сканирование, соединения) — как обычно, с распакованными данными. Преимущества:

  • Меньше I/O — особенно важно для аналитических запросов, которые читают много данных.

  • Почти нулевая CPU-нагрузка — потому что сжатие/распаковка очень лёгкие (часто используется LZ4 или аналоги).

  • Каждая БД — это логический контейнер.

  • Физически — это подкаталог в base/ с OID’ом базы.

  • Базы полностью изолированы: у них свои таблицы, схемы, пользователи (хотя пользователи на самом деле глобальны — хранятся в global/!).

Как всё взаимодействует? Простой пример

  1. Клиент подключается к порту 5432.
  2. Postmaster принимает подключение и запускает backend-процесс.
  3. Backend:
    • Читает системные каталоги из global/ и base/... → кэширует в shared memory.
    • При запросе SELECT * FROM orders:
      • Ищет файл таблицы в base/<OID_БД>/.
      • Если страница не в shared_buffers → читает с диска → кладёт в буфер.
      • Использует ProcArray и MVCC, чтобы понять, какие строки “видны” этой транзакции.
  4. При UPDATE:
    • Создаётся новая версия строки (MVCC).
    • Изменения пишутся в shared_buffers и WALwal_buffers, потом на диск в pg_wal/).
    • WAL writer и background writer позже сбрасывают это на диск.
  5. Autovacuum позже уберёт старую “мёртвую” версию строки.