
У всех, кто эксплуатирует Postgres под нагрузкой, есть один и тот же неприятный ритуал. Таблица за годы UPDATE/DELETE распухла, физический размер в разы больше реальных данных, индексы раздулись, диск кончается. Лечится это перепаковкой — но VACUUM FULL берёт ACCESS EXCLUSIVE lock на всю таблицу, то есть кладёт по ней любые чтения и записи на всё время операции. На терабайтной таблице это окно простоя, которое согласовывают неделями.
Стандартный обходной путь — внешнее расширение pg_repack: оно перепаковывает таблицу почти без блокировки, ловя изменения через триггеры и применяя их на копию. Работает, но это сторонняя зависимость, со своими нюансами по правам, индексам и внешним ключам.
4 июня 2026 вышла PostgreSQL 19 Beta 1, и там эта боль наконец закрывается штатно: в ядро завезли команду REPACK с неблокирующей опцией CONCURRENTLY. Это, на мой взгляд, главная операционная фича релиза — и про неё стоит говорить раньше, чем про распиаренные графовые запросы. Разберём обе, по официальному анонсу и release notes, без «я проверил в проде» — beta в прод не ставят.
REPACK (CONCURRENTLY): перепаковка без окна простоя
Идея та же, что у pg_repack, но теперь это часть СУБД, а не внешний бинарник. Опции, как и у других команд, идут в скобках:
-- блокирующая перепаковка (как VACUUM FULL — берёт ACCESS EXCLUSIVE)
REPACK orders;
-- неблокирующая: таблица остаётся доступной на чтение и запись
REPACK (CONCURRENTLY) orders;
REPACK (CONCURRENTLY) пересобирает таблицу и её индексы в новые файлы, освобождая раздутое место, и не держит эксклюзивную блокировку всё время работы. Изменения, прилетевшие в таблицу во время операции, захватываются через logical decoding (а не триггерами, как у pg_repack) и накатываются на новую копию; короткий тяжёлый lock остаётся только на финальную atomic-подмену — как у REINDEX CONCURRENTLY. Отсюда и новая серверная переменная max_repack_replication_slots: каждый одновременный repack забирает дополнительный слот репликации, а верхняя граница параллелизма задаётся этим параметром и общими ресурсными лимитами.
И вот тут — самое важное для тех, кто собрался катить это на прод. REPACK (CONCURRENTLY) не является MVCC-safe: документация прямо предупреждает, что транзакция со старым снапшотом в некоторых сценариях может увидеть перепакованную таблицу пустой. Для операционной команды это не мелкая сноска, а то, что нужно держать в голове, планируя окно.
Documented-ограничения беты, которые отсекают часть кейсов сразу — CONCURRENTLY нельзя применить:
к
UNLOGGED-таблицам, секционированным таблицам, системным каталогам и TOAST;к таблицам без primary key или index-based replica identity (логично: иначе нечем сопоставлять строки при логическом декодировании);
внутри transaction block;
а ещё операция может не завершиться, если по таблице параллельно пойдёт DDL.
Что прогнать на staging до GA:
Дисковый оверхед. Перепаковка строит новую копию таблицы и индексов: нужно место минимум под таблицу + индексы, а на пике (seq scan + сортировка) — до двойного размера таблицы плюс индексы. Для терабайтника это не мелочь.
Бюджет слотов и лаг репликации. Если уже есть физические/логические реплики — посчитайте слоты заранее, иначе упрётесь.
Поведение под нагрузкой на копии самых проблемных таблиц, с поправкой на MVCC-оговорку выше.
Заменит ли он pg_repack полностью? Для типового «раздуло таблицу, нужно вернуть место без даунтайма» — во многом да, и без внешней зависимости. Но с оглядкой на список ограничений выше и не раньше, чем прогоните на своих данных.
SQL/PGQ: графовые запросы без отдельной графовой БД
Вторая большая фича — нативные property-graph запросы по стандарту SQL/PGQ (часть SQL:2023, GRAPH_TABLE). Ключевое, что многие пропускают: это не новое хранилище. Граф описывается как метаданные поверх таблиц, которые у вас уже есть — фактически view. Данные не дублируются и не синхронизируются, Postgres переписывает graph-паттерн в обычные джойны на этапе планирования.
-- граф — это метаданные над существующими users/posts/follows
CREATE PROPERTY GRAPH social_graph
VERTEX TABLES (
users LABEL person PROPERTIES (id, name),
posts LABEL post PROPERTIES (id, title)
)
EDGE TABLES (
follows
SOURCE KEY (follower_id) REFERENCES users (id)
DESTINATION KEY (followed_id) REFERENCES users (id)
LABEL follows
);
-- на кого подписана Alice
SELECT followed_name
FROM GRAPH_TABLE (social_graph
MATCH (a IS person WHERE a.name = 'Alice')
-[IS follows]->
(b IS person)
COLUMNS (b.name AS followed_name)
);
То, что раньше было лесенкой из самоджойнов или рекурсивного CTE, становится читаемым паттерном (a)-[follows]->(b). Для follower-графов, деревьев зависимостей, тегов и прочих связей средней глубины это снимает реальную боль — и убирает из стека отдельный Neo4j, который держали только ради двух графовых запросов.
Но честная граница Beta 1: переменной длины пути пока нет. То есть «найди всех, до кого можно дойти за 1…N переходов» (классический обход графа неизвестной глубины) этим синтаксисом ещё не выразить — это всё ещё территория рекурсивных CTE или специализированных графовых движков. Так что SQL/PGQ закрывает паттерны фиксированной глубины, а не заменяет графовую БД целиком.
Что ещё приехало
Коротко, чтобы было видно вектор релиза:
Параллельный autovacuum (
autovacuum_max_parallel_workers) и новая система приоритизации таблиц для вакуума — давняя боль больших баз.Автоскейлинг I/O-воркеров поверх асинхронного I/O из 18-й версии (
io_min_workers/io_max_workers).pg_plan_advice/pg_stash_advice— стабилизация и контроль решений планировщика без хаков сpg_hint_plan.До 2x быстрее INSERT при наличии проверок внешних ключей, плюс пачка оптимизаций планировщика (anti-join, инкрементальные сортировки, eager aggregation).
Вывод
Графовые запросы — красивый заголовок, но для большинства из нас новость релиза в другом: рутинная перепаковка раздутых таблиц перестаёт требовать окна простоя и внешнего расширения. REPACK (CONCURRENTLY) — это та фича, ради которой стоит поднять PostgreSQL 19 на staging уже сейчас и прогнать на копии своих самых проблемных таблиц: проверить дисковый оверхед, бюджет слотов и documented-ограничения (включая то, что команда не MVCC-safe) до того, как версия дойдёт до GA.
SQL/PGQ берите как приятный бонус: для связей фиксированной глубины он реально убирает отдельную графовую БД из стека, но обходы переменной глубины пока мимо.
А вы чем сейчас перепаковываете раздутые таблицы — pg_repack, VACUUM FULL в окно, pg_squeeze или живёте с bloat’ом до мажорного обновления?






















