Открыть сервис

Темпоральные таблицы

Темпоральные таблицы (англ. temporal tables, также таблицы с поддержкой времени, системно-версионированные таблицы) — это механизм реляционных баз данных, предназначенный для автоматического хранения и предоставления доступа к историческим изменениям данных в строках таблицы. В отличие от обычных таблиц, которые хранят только текущее состояние данных, темпоральные таблицы позволяют выполнять запросы к данным на любой момент времени в прошлом, обеспечивая полную историю изменений каждой записи.

Основные принципы

Темпоральные таблицы реализуют концепцию управления данными с учётом времени (temporal data management). В основе лежит идея, что каждая строка данных имеет период актуальности, в течение которого она считается верной. Этот период задаётся двумя служебными столбцами, автоматически управляемыми системой управления базами данных (СУБД):

  • Столбец начала периода (SysStartTime, ValidFrom): фиксирует момент времени, когда строка была вставлена или изменена и стала актуальной.
  • Столбец окончания периода (SysEndTime, ValidTo): фиксирует момент времени, когда строка перестала быть актуальной (была обновлена или удалена).

Для обычной строки, которая является текущей, значение в столбце окончания периода часто устанавливается как максимально возможное (например, 9999-12-31 23:59:59.9999999). При обновлении или удалении строки СУБД автоматически копирует старую версию строки в отдельную историческую таблицу, устанавливая для неё дату окончания периода, равную времени выполнения операции.

Классификация

В теории баз данных и в стандарте SQL:2011 выделяют два основных типа темпоральных таблиц, которые могут применяться как по отдельности, так и совместно:

Системно-версионированные темпоральные таблицы (System-Versioned Temporal Tables, SVTT)

Управление временными метками полностью автоматизировано СУБД. Пользователь не может напрямую изменять служебные столбцы. Система сама фиксирует время вставки, обновления и удаления строк на основе системных часов сервера. Этот тип наиболее распространён в современных СУБД (Microsoft SQL Server 2016+, PostgreSQL с расширением pg_period, MariaDB 10.3+, Oracle 12c+). Он удобен для аудита, отладки и восстановления данных на определённый момент времени.

Таблицы с временем прикладного уровня (Application-Time Period Tables, Bitemporal Tables)

Управление временными метками осуществляется пользователем или приложением. В таких таблицах время актуальности строки задаётся бизнес-логикой и может не совпадать с реальным временем изменения записи в базе. Например, дата вступления в силу нового тарифа может быть задана на будущее, а дата его окончания — на прошлое. Этот тип требует явного указания периодов при вставке и обновлении данных. Часто используется в системах, где важна дата события, а не дата его регистрации в системе (например, в бухгалтерском учёте, кадровом делопроизводстве).

Битемпоральные таблицы (Bitemporal Tables)

Сочетают оба подхода: системное время (когда факт был зафиксирован в базе) и прикладное время (когда факт был актуален в реальности). Это позволяет, например, узнать, какой тариф действовал для клиента 1 января 2023 года, и при этом увидеть, какой была база данных на 5 января 2023 года (то есть до того, как была исправлена ошибка в дате тарифа). Битемпоральные таблицы реализованы в Oracle Database и частично в IBM Db2.

Устройство и реализация

Архитектурно темпоральная таблица состоит из двух физических таблиц:

  1. Текущая таблица (Current Table): хранит только актуальные (последние) версии строк. По структуре она идентична обычной таблице, но содержит два дополнительных служебных столбца для периода.
  2. Историческая таблица (History Table): хранит все предыдущие версии строк, которые были изменены или удалены. Структура исторической таблицы идентична структуре текущей, за исключением того, что в ней не может быть первичного ключа (так как одна и та же строка может иметь несколько исторических версий).

СУБД автоматически управляет перемещением данных между этими таблицами. При выполнении UPDATE или DELETE над строкой в текущей таблице, её старая версия копируется в историческую таблицу, а в текущей таблице остаётся новая версия (или строка удаляется). При INSERT новая строка сразу помещается в текущую таблицу.

Для выполнения запросов к историческим данным используется специальный синтаксис, чаще всего конструкция FOR SYSTEM_TIME AS OF <дата>. Этот синтаксис позволяет СУБД объединять данные из текущей и исторической таблиц, возвращая состояние данных на указанный момент времени.

Применение

Темпоральные таблицы находят широкое применение в различных областях:

  • Аудит и комплаенс: Автоматическая фиксация всех изменений данных без необходимости писать триггеры или отдельные процедуры журналирования. Это соответствует требованиям многих регуляторов (например, в финансовом секторе и здравоохранении).
  • Анализ данных и отчётность: Возможность строить отчёты, показывающие состояние данных на любой момент времени (например, «сколько сотрудников работало в компании на 1 января каждого года»).
  • Восстановление данных после ошибок: Быстрое восстановление случайно изменённых или удалённых записей без использования резервных копий. Можно выполнить запрос к данным на момент до ошибки и вставить их обратно.
  • Управление версиями справочников: Хранение истории изменений справочных данных (например, номенклатуры товаров, курсов валют, тарифов).
  • Медленно меняющиеся измерения (SCD) в хранилищах данных: Тип 2 (SCD Type 2) может быть реализован с помощью темпоральных таблиц, что упрощает ETL-процессы.

Преимущества и недостатки

Преимущества

  • Автоматизация: СУБД сама управляет историей, что снижает вероятность ошибок и упрощает код приложений.
  • Прозрачность: Для обычных запросов (SELECT, INSERT, UPDATE, DELETE) темпоральная таблица ведёт себя как обычная. Исторические данные не видны, пока не используется специальный синтаксис.
  • Производительность: Исторические данные хранятся отдельно, что не замедляет запросы к текущим данным. Для исторических запросов могут быть созданы отдельные индексы.
  • Целостность: Система гарантирует, что временные метки корректны и не могут быть изменены пользователем (для системно-версионированных таблиц).

Недостатки

  • Рост объёма данных: Историческая таблица может быстро расти, особенно при частых обновлениях. Требуется планирование управления ёмкостью хранения и политики архивации.
  • Ограничения DDL: Некоторые операции изменения схемы таблицы (например, изменение типа данных столбца) могут быть затруднены или требовать временного отключения версионирования.
  • Сложность битемпоральных таблиц: Реализация и понимание битемпоральных таблиц требуют более высокой квалификации разработчика.
  • Зависимость от СУБД: Реализация темпоральных таблиц может отличаться в разных СУБД, что усложняет миграцию.

Примеры реализации в СУБД

  • Microsoft SQL Server (2016+): Реализованы системно-версионированные темпоральные таблицы. Синтаксис: CREATE TABLE ... WITH (SYSTEM_VERSIONING = ON).
  • PostgreSQL: Стандартной реализации нет, но существует расширение pg_period (от 2ndQuadrant) и temporal_tables. В PostgreSQL 12+ появилась поддержка генерируемых столбцов, что упрощает создание подобных решений.
  • MariaDB (10.3+): Реализованы системно-версионированные темпоральные таблицы. Синтаксис: CREATE TABLE ... WITH SYSTEM VERSIONING.
  • Oracle (12c+): Поддерживаются системно-версионированные и битемпоральные таблицы через механизм Flashback Data Archive (Oracle Total Recall) и использование периодов времени.
  • IBM Db2: Поддерживает битемпоральные таблицы с использованием бизнес-времени и системного времени.

Источники

  • Стандарт SQL:2011 (ISO/IEC 9075:2011), раздел по темпоральным таблицам.
  • Документация Microsoft SQL Server: «Temporal Tables».
  • Документация MariaDB: «System-Versioned Tables».
  • Документация Oracle Database: «Temporal Validity Support» и «Flashback Data Archive».
  • Книга: C. J. Date, Hugh Darwen, Nikos Lorentzos. «Temporal Data and the Relational Model».

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →