Сайт использует сookies для хранения данных. Продолжая использовать сайт, вы даёте согласие на работу с этими файлами.

ОК
🧱
Данные
Опубликовано:
14.08.2026
Обновлено:
14.08.2026

Логическая репликация generated columns в PostgreSQL 18: где это реально полезно

Артём Целин

PostgreSQL 18 впервые позволяет передавать stored generated columns через логическую репликацию. До этой версии сгенерированные столбцы полностью игнорировались подписчиками, поэтому любые вычисляемые значения приходилось пересчитывать на стороне приёмника или вовсе терять при интеграции с внешними системами. Появление параметра publish_generated_columns и поддержки явного списка колонок в публикации меняет правила игры: теперь можно осмысленно доставлять готовые производные данные в аналитические платформы, стриминговые системы и другие кластеры PostgreSQL.

Зачем нужна репликация generated columns и что этому мешало раньше

Generated columns — это столбцы, значение которых вычисляется на основе выражения, заданного при создании таблицы. В PostgreSQL поддерживаются два типа: STORED (физически хранится на диске) и VIRTUAL (вычисляется на лету, не хранится). В версиях до 18 логическая репликация не обрабатывала ни один из этих типов: при начальной синхронизации таблиц и при передаче изменений generated columns просто не попадали в поток данных.

На практике это означало, что любой подписчик — будь то другой кластер PostgreSQL или внешняя система — должен был самостоятельно вычислять такие столбцы. Для PostgreSQL это ещё было терпимо: можно было повторить выражение в схеме подписчика. Однако для не-PostgreSQL-подписчиков, например аналитических хранилищ, брокеров сообщений или ETL-платформ, воспроизвести ту же логику зачастую невозможно или крайне неудобно. Ценная производная информация, уже рассчитанная на источнике, пропадала, и интеграция требовала дополнительных ухищрений.

Именно поэтому сообщество признало репликацию generated columns важным шагом к зрелости логической репликации как средства интеграции данных.

Что изменилось в PostgreSQL 18

В PostgreSQL 18 появилась целенаправленная поддержка логической репликации stored generated columns. Виртуальные столбцы по-прежнему не участвуют в репликации: они не имеют физического представления, и механизм logical decoding не может их извлечь. Стоит отметить, что в версии 18 виртуальные сгенерированные столбцы стали типом по умолчанию, если при создании не указано иное, однако это не меняет запрета на их репликацию.

Ключевое изменение — новый параметр публикации publish_generated_columns. Он управляет тем, будут ли stored generated columns публиковаться как обычные столбцы:

  • none (значение по умолчанию) — сгенерированные столбцы не публикуются, поведение идентично версиям до 18.
  • stored — все stored generated columns, определённые в таблицах публикации, автоматически включаются в репликацию.

Также появилась возможность управлять репликацией сгенерированных столбцов на уровне отдельных таблиц через явный список колонок в команде создания публикации. Например:

CREATE PUBLICATION my_pub FOR TABLE my_table (id, data, gen_column);

Такой список имеет приоритет над publish_generated_columns: если столбец явно перечислен, он будет реплицироваться как обычный, независимо от значения параметра. И наоборот — если сгенерированный столбец не попал в явный список, он не реплицируется.

На стороне подписчика никаких специальных действий не требуется, кроме одного важного условия: целевой столбец должен быть обычным, а не GENERATED. Попытка направить реплицируемое значение в generated-столбец на подписчике вызовет ошибку, потому что PostgreSQL запрещает прямую запись в такие поля.

Практические сценарии: где это реально полезно

Передача вычисленных данных во внешние аналитические системы и стриминг

Один из главных мотивов появления фичи — поддержка non-PostgreSQL-подписчиков. Если вы используете логическую репликацию для доставки данных в аналитическую БД, хранилище данных (DWH) или стриминговую платформу через протокол logical decoding, то раньше вам приходилось либо отказываться от generated columns, либо дублировать логику вычислений на стороне приёмника. PostgreSQL 18 решает эту проблему, отправляя уже вычисленные значения stored-столбцов.

Типичный пример: в таблице заказов есть сгенерированный столбец total_price, вычисляемый как quantity * unit_price. Внешняя система, например аналитическая платформа на основе ClickHouse или Kafka Connect, не знает выражение и не обязана его воспроизводить. Теперь паблишер может передать готовое значение, и приёмник получит его как обычное поле без какой-либо доработки.

Миграции и обновления схем с generated columns

При переносе схем между средами или при репликации между кластерами, находящимися на разных этапах развития, stored generated columns нередко содержат критичные производные данные. Раньше при миграции приходилось либо вручную пересчитывать их на новом месте, либо менять подход к хранению (например, делать столбцы обычными и управлять значениями через триггеры). Теперь можно просто включить репликацию этих столбцов и получить полную консистентность без дублирования выражений.

В чек-лист любой миграции с PostgreSQL 18 стоит добавить пункт: проверить, нужно ли переносить stored generated columns. Если да — достаточно указать publish_generated_columns = stored или включить нужные колонки в явный список, и подписчик получит их как часть схемы.

Каскадная репликация и многоверсионные ландшафты

В сложных системах с каскадной репликацией (паблишер → подписчик → следующий подписчик) generated columns могут осмысленно передаваться по цепочке. Если все узлы используют PostgreSQL 18, можно настроить сквозную передачу вычисленных значений, не заставляя промежуточные инстансы пересчитывать их. Это уменьшает накладные расходы и снижает риск расхождения данных при изменении логики вычислений.

Как настроить и проверить: код и примеры

Настройка сводится к изменению публикации на стороне источника. Предположим, есть таблица с одним сгенерированным столбцом:

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    quantity INT,
    unit_price NUMERIC,
    total_price NUMERIC GENERATED ALWAYS AS (quantity * unit_price) STORED
);

Создаём публикацию с включённой репликацией stored generated columns:

CREATE PUBLICATION orders_pub FOR TABLE orders
    WITH (publish_generated_columns = stored);

Теперь столбец total_price будет передаваться подписчику как обычное поле. Если нужно реплицировать только часть сгенерированных столбцов или, наоборот, исключить некоторые из них, можно воспользоваться явным списком колонок:

CREATE PUBLICATION orders_pub FOR TABLE orders (id, quantity, unit_price, total_price);

Проверить, какие столбцы попадают в публикацию, можно через представление pg_publication_tables в системном каталоге.

На подписчике достаточно создать таблицу с обычным столбцом total_price:

CREATE TABLE orders (
    id INT PRIMARY KEY,
    quantity INT,
    unit_price NUMERIC,
    total_price NUMERIC   -- обычный столбец, не GENERATED
);

После создания подписки данные, включая значение total_price, начнут поступать.

Ограничения и подводные камни

Хотя фича заметно расширяет возможности логической репликации, важно помнить о нескольких принципиальных ограничениях.

  • Только STORED columns. Виртуальные generated columns (VIRTUAL) не имеют физического хранилища и не могут быть реплицированы. Они остаются полностью локальными для сервера-источника.
  • Целевой столбец должен быть обычным. Если на подписчике столбец объявлен как GENERATED, попытка вставить в него реплицируемое значение приведёт к ошибке, потому что PostgreSQL блокирует прямую запись в generated-столбцы.
  • Несовместимость с подписчиками до версии 18. При начальной синхронизации таблиц на подписчике с PostgreSQL 17 или старше сгенерированные столбцы не копируются. Для полноценной работы с репликацией generated columns подписчик должен работать на PostgreSQL 18.
  • Приоритет явного списка колонок. Если в команде CREATE PUBLICATION используется явный список столбцов, параметр publish_generated_columns игнорируется. Публикуются только столбцы, перечисленные в этом списке.
  • Альтернативы всё ещё актуальны. Если требуется, чтобы выражение вычислялось на стороне подписчика (например, для разных версий расчёта), то generated columns на источнике лучше не реплицировать. В таких случаях можно оставить значение по умолчанию none или исключить их из явного списка.

FAQ

Можно ли реплицировать виртуальные generated columns?
Нет. Виртуальные столбцы не хранятся на диске и не могут быть извлечены через механизм logical decoding. Реплицируются только stored generated columns.

Что будет, если на подписчике столбец тоже объявлен GENERATED?
Применение изменений завершится ошибкой. PostgreSQL не разрешает напрямую записывать значения в сгенерированный столбец, поэтому на подписчике такой столбец должен быть определён как обычный.

Как включить репликацию только для отдельных сгенерированных столбцов?
Используйте явный список колонок при создании публикации: CREATE PUBLICATION ... FOR TABLE t (col1, gen_col2, ...). В этом случае параметр publish_generated_columns не действует, и реплицируются только перечисленные столбцы.

Работает ли это с подписчиком на PostgreSQL 17?
При начальной синхронизации таблиц на подписчике версии 17 сгенерированные столбцы не копируются. Для репликации изменений в реальном времени также ожидаются трудности, так как механизм логической репликации в версии 17 не поддерживает передачу generated columns. Рекомендуется обновить подписчик до PostgreSQL 18.

Копируются ли generated columns при начальной синхронизации таблицы?
Да, если подписчик работает на PostgreSQL 18 и целевой столбец является обычным, то stored generated columns будут скопированы как часть начальной синхронизации. Их значения передаются точно так же, как и для любых других столбцов.

Можно ли передавать выражение столбца, а не вычисленное значение?
Нет. Логическая репликация передаёт уже вычисленное значение stored-столбца. Определение выражения остаётся только на паблишере и не реплицируется.

Вывод

Логическая репликация generated columns в PostgreSQL 18 — это не просто техническое улучшение, а реальный инструмент для упрощения интеграций и миграций. Возможность доставлять готовые производные данные избавляет от необходимости дублировать логику вычислений на стороне подписчиков, особенно когда речь идёт о внешних аналитических системах и стриминговых платформах. При этом важно чётко понимать ограничения: только stored-столбцы, только обычные колонки на приёмнике и обязательное использование PostgreSQL 18 на подписчике. Взвешенное применение нового параметра publish_generated_columns и явных списков столбцов позволяет сделать архитектуру репликации более гибкой и прозрачной.

Источники

Это авторская статья, основанная на личном опыте и субъективном взгляде автора. Заметили ошибку или битую ссылку? Сообщите нам: info@codesrc.ru - мы оперативно исправим. Спасибо, что помогаете делать блог лучше.
Следите за нами в соцсетях:

Читайте также