Postgres 19 наконец отвечает: как эта строка выглядела в прошлый вторник?
Годами запросы с путешествием во времени в Postgres означали самодельные диапазоны дат и гимнастику с GIST-индексами. PG19 приносит темпоральные возможности SQL:2011 нативно: первичные ключи без пересечений, обновления по временным срезам и внешние ключи на период действия. Инженер, который это сделал, появился в треде.
Postgres 19 добавляет нативные темпоральные таблицы по времени приложения: PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) заменяет пляску с EXCLUDE USING gist, FOR PORTION OF позволяет UPDATE переписать лишь один временной срез, а внешние ключи PERIOD следят за действительностью на всём промежутке.
Разработчик, реализовавший это, зашёл в тред и сказал: системного времени всё ещё нет, и он надеётся взяться за него следующим. А автор статьи назвал это крупнейшим релизом со времён v10.
Запрос, на который Postgres до сих пор не отвечал нативно

Каламбур в обзоре pgEdge буквальный: PostgreSQL 19 — про время. Он наконец выпускает нативные темпоральные таблицы по времени приложения из стандарта SQL:2011, способные ответить на вопрос «как эти данные выглядели в прошлый вторник?» без самодельного журнала аудита.
Что на самом деле нового в PG19
Три возможности тянут на себе релиз, по словам автора Шона Томаса:
- Первичные ключи
WITHOUT OVERLAPS:PRIMARY KEY (product_id, valid_at WITHOUT OVERLAPS)заменяет громоздкое ограничениеEXCLUDE USING gistи ручную настройкуbtree_gist, по-прежнему не допуская двух пересекающихся периодов действия. FOR PORTION OF:UPDATE … FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-09-01'переписывает только этот срез времени, а Postgres сам разбивает и подгоняет соседние строки.- Внешние ключи
PERIOD: темпоральная ссылочная целостность: строка, на которую ссылаются, должна существовать на всём промежутке действия ссылающейся.
Приложения хранят один столбец-диапазон (например, DATERANGE) вместо отдельных полей valid_from / valid_to. Заметный пробел: таблиц по системному времени (времени транзакции) всё ещё нет, так что их эмулируют триггерами или расширением pg_bitemporal.
В тред зашёл тот, кто это построил
Лучшее подтверждение пришло от реализовавшего:
«Эй, я над этим работал!… Часто слышу сомнения, что это кому-то нужно. Возможно, поэтому вендоры так медленно это добавляли… Системного времени у нас пока нет, но если никто другой не возьмётся, надеюсь, скоро доберусь до него». — разработчик, реализовавший темпоральные таблицы
Автор статьи, администратор баз данных, обрисовал масштаб релиза:
«Postgres 19 обещает быть солидным релизом. Кажется, столько „нового“ в одной версии я не видел с выхода v10». — администратор баз данных, работающий с PostgreSQL с 2005 года
Практики пришли с той самой болью, которую это снимает. Разработчик, вручную собиравший версионируемые периоды, привёл канонический сценарий: ставку налога с продаж ввели как 7,25% на 2026 год, позже исправили на 7,35% — и нужно зафиксировать, что она всегда была 7,35% с января, а не изменилась в день правки. Другие вспоминали торговые системы, обрабатывающие сообщения о коррекции и отмене сделок.
Одно допущение, которое оно тихо ломает
Не всем спокойно. Из-за этой возможности UPDATE вставляет новые строки, когда разбивает диапазон, и это сбивает давно укоренившуюся модель:
«Мне немного не по себе от того, что операции UPDATE добавляют новые строки в таблицу. Это рушит многие допущения администратора баз данных». — ris
Аргумент для всех, кто ведёт журналы аудита, историю цен или расписания: учёт, который вы десять лет писали руками, становится ограничением на столбец. Честная оговорка: это половина битемпоральности — время приложения. Вторая половина ждёт PG20 или того, что у реализовавшего найдётся время.
Получайте такие разборы каждый день
Главные истории Hacker News — на email, в Telegram или RSS.
Фермент CRISPR читает мутантную РНК рака и кромсает клетку изнутри
Cas9 режет ДНК в одной точке. Cas12a2 делает кое-что страннее: заметив РНК-транскрипт, который есть только в опухоли, он впадает в неистовство и крошит в клетке всё подряд. Спусковой крючок — различие в один нуклеотид между больной клеткой и здоровой.