Создание системной темпоральной таблицы
Область применения: SQL Server 2016 (13.x) и более поздние версии
База данных SQL Azure
Управляемый экземпляр SQL Azure
База данных SQL в Microsoft Fabric
Существует три способа создания темпоральной таблицы с системным управлением версиями, в зависимости от того, как указывается таблица историй.
Темпоральная таблица с анонимной исторической таблицей: вы указываете схему текущей таблицы и позволяете системе создавать соответствующую историческую таблицу с автоматически сгенерированным именем.
Темпоральная таблица с таблицей журнала по умолчанию: вы указываете имя схемы таблицы журнала и имя таблицы и позволяете системе создавать таблицу журнала в этой схеме.
Темпоральная таблица с определяемой пользователем таблицей журнала, созданной заранее: вы создаете таблицу журнала, которая соответствует вашим потребностям, а затем ссылается на эту таблицу во время создания темпоральной таблицы.
Создайте темпоральную таблицу с анонимной исторической таблицей
Создание временной таблицы с анонимнойтаблицей журнала является удобным способом быстрого создания объектов данных, особенно в прототипах и тестовых окружениях. Это также самый простой способ создания темпоральной таблицы, так как он не требует каких-либо параметров в предложении SYSTEM_VERSIONING
. В следующем примере создается новая таблица с включенным системным версионированием без определения имени исторической таблицы.
CREATE TABLE Department
(
DeptID INT NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR(50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON);
Замечания
Системная темпоральная таблица должна иметь определённый первичный ключ и точно одну PERIOD FOR SYSTEM_TIME
, связанную с двумя столбцами datetime2, объявленными как GENERATED ALWAYS AS ROW START
или GENERATED ALWAYS AS ROW END
.
Столбцы PERIOD
всегда считаются не допускающими значение NULL, даже если это свойство специально не указано.
PERIOD
Если столбцы явно определены как допускающие значение NULL, инструкция завершается ошибкойCREATE TABLE
.
Таблица истории всегда должна быть согласована по схеме с актуальной или временной таблицей с точки зрения количества столбцов, их имен, порядка и типов данных.
Анонимная таблица истории автоматически создается в той же схеме, что и текущая или темпоральная таблица.
Имя анонимной таблицы истории имеет следующий формат: MSSQL_TemporalHistoryFor_<current_temporal_table_object_id>_<suffix>
Суффикс является необязательным и добавляется только в том случае, если первая часть имени таблицы не является уникальной.
Таблица истории создается как таблица rowstore.
PAGE
сжатие применяется, если это возможно, в противном случае таблица истории остаётся нераспакованной. Например, некоторые конфигурации таблиц, такие как SPARSE
столбцы, не разрешают сжатие.
Кластеризованный индекс по умолчанию создается для таблицы журнала с автоматически созданным именем в формате IX_<history_table_name>
. Кластеризованный индекс содержит PERIOD
столбцы (конец, начало).
В базе данных SQL Fabric созданная таблица журнала не отображается в Fabric OneLake.
Сведения о создании текущей таблицы в качестве оптимизированной для памяти таблицы см. в статье "Системные версии темпоральных таблиц с оптимизированными для памяти таблицами".
Создать временную таблицу с исторической таблицей по умолчанию
Создание темпоральной таблицы с таблицей журнала по умолчанию удобно, если вы хотите управлять именованием и по-прежнему полагаться на систему, чтобы создать таблицу журнала с конфигурацией по умолчанию . В следующем примере создается новая таблица с включенной поддержкой системного версионирования и явно заданным именем таблицы истории.
CREATE TABLE Department
(
DeptID INT NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR(50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.DepartmentHistory));
Замечания
Таблица истории создается по тем же правилам, которые применяются при создании "анонимной" таблицы истории, с применением следующих особых правил, касающихся именованной таблицы.
Имя схемы является обязательным для
HISTORY_TABLE
параметра.Если указанная схема не существует, инструкция
CREATE TABLE
вызовет ошибку.Если таблица, указанная параметром
HISTORY_TABLE
, уже существует, она проверяет соответствие созданной временной таблице с точки зрения согласованности схем и согласованности временных данных. Если указать недопустимую таблицу журнала, инструкция завершается ошибкойCREATE TABLE
.
Создание временной таблицы с определяемой пользователем таблицей истории
Создание темпоральной таблицы с определяемой пользователем таблицей журнала является удобным вариантом, когда пользователь хочет указать таблицу журнала с определенными параметрами хранения и различными индексами, настроенными на исторические запросы. В следующем примере создается определяемая пользователем таблица журнала с схемой, выровненной с созданной темпоральной таблицей. Для этой пользовательской таблицы истории создается кластеризованный индекс columnstore и дополнительный некластеризованный индекс хранилища строк (B-tree) для точечных запросов. После создания этой пользовательской таблицы журнала создается темпоральная таблица, указывающая определяемую пользователем таблицу журнала в качестве таблицы журнала по умолчанию.
Примечание.
В документации термин B-tree обычно используется в ссылке на индексы. В индексах rowstore ядро СУБД реализует дерево B+. Это не относится к индексам columnstore или индексам в таблицах, оптимизированных для памяти. Дополнительные сведения см. в руководстве по архитектуре и проектированию индексов SQL Sql Server и Azure.
CREATE TABLE DepartmentHistory
(
DeptID INT NOT NULL,
DeptName VARCHAR(50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 NOT NULL,
ValidTo DATETIME2 NOT NULL
);
GO
CREATE CLUSTERED COLUMNSTORE INDEX IX_DepartmentHistory ON DepartmentHistory;
CREATE NONCLUSTERED INDEX IX_DepartmentHistory_ID_Period_Columns
ON DepartmentHistory (ValidTo, ValidFrom, DeptID);
GO
CREATE TABLE Department
(
DeptID int NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR(50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.DepartmentHistory));
Замечания
Если вы планируете выполнять аналитические запросы на исторических данных, в которых используются агрегатные или оконные функции, настоятельно рекомендуется создать кластеризованное хранилище столбцов в качестве первичного индекса, так как это позволяет значительно улучшить сжатие данных и производительность запросов.
Если вы планируете использовать темпоральные таблицы для аудита данных (то есть поиск исторических изменений для одной строки из текущей таблицы), следует создать таблицу журнала rowstore с кластеризованным индексом.
Таблица журнала не может иметь первичный ключ, внешние ключи, уникальные индексы, ограничения таблицы или триггеры. Его нельзя настроить для отслеживания измененных данных, отслеживания изменений, репликации транзакций или репликации слиянием.
В базе данных SQL Fabric и в базе данных SQL Azure с настроенным зеркалированием Fabric, при использовании существующей таблицы в качестве журнальной таблицы во время создания темпоральной таблицы, существующая таблица перестает зеркалироваться.
Преобразование нетемпоральной таблицы в системно-версируемую темпоральную таблицу
Вы можете включить системное управление версиями в существующей не временной таблице, например, при необходимости перенести пользовательское темпоральное решение на встроенную поддержку.
Например, у вас может быть набор таблиц, в которых управление версиями реализуется с помощью триггеров. Использование темпоральной системы управления версиями менее сложно и предоставляет другие преимущества, в том числе:
- неизменяемая история
- Новый синтаксис для временных запросов
- улучшенная производительность DML;
- минимальные затраты на обслуживание.
При преобразовании существующей таблицы рекомендуется использовать предложение HIDDEN
для скрытия новых столбцов PERIOD
(столбцов и ValidFrom
datetime2) для предотвращения влияния на существующие приложения, которые явно не указывают имена столбцов (например, SELECT *
или INSERT
без списка столбцов) и не предназначены для обработки новых столбцов.
Добавьте версионность в нетемпоральные таблицы
Если вы хотите начать отслеживание изменений для нетемпоральной таблицы, содержащей данные, необходимо добавить определение PERIOD
и при необходимости указать имя пустой таблицы журнала, которую создает SQL Server.
CREATE SCHEMA History;
GO
ALTER TABLE InsurancePolicy ADD
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN
CONSTRAINT DF_InsurancePolicy_ValidFrom DEFAULT SYSUTCDATETIME(),
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN
CONSTRAINT DF_InsurancePolicy_ValidTo DEFAULT CONVERT(DATETIME2, '9999-12-31 23:59:59.9999999'),
PERIOD FOR SYSTEM_TIME(ValidFrom, ValidTo);
GO
ALTER TABLE InsurancePolicy
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = History.InsurancePolicy));
GO
Внимание
Точность DATETIME2
должна соответствовать точности базовой таблицы.
Замечания
Добавление ненуляемых столбцов с значениями по умолчанию в существующую таблицу с данными — это размер операции с данными во всех выпусках, отличных от выпуска SQL Server Enterprise (в котором это операция метаданных). При большой существующей таблице истории с данными в редакции SQL Server Standard добавление столбца, не допускающего значения NULL, может быть дорогой операцией.
Необходимо тщательно выбрать ограничения для столбцов начала и окончания периода:
Значение по умолчанию для столбца начала определяет, начиная с какого момента времени существующие строки должны считаться действительными. Это невозможно указать как точку времени в будущем.
Время окончания должно быть указано как максимальное значение для заданной точности datetime2, например
9999-12-31 23:59:59
или9999-12-31 23:59:59.9999999
.
Добавление PERIOD
выполняет проверку согласованности данных в текущей таблице, чтобы убедиться, что существующие значения для столбцов периода допустимы.
Если при включении SYSTEM_VERSIONING
указана существующая таблица журнала, проверка согласованности данных выполняется как в текущей, так и в таблице журнала. Его можно пропустить, если указать DATA_CONSISTENCY_CHECK = OFF
в качестве дополнительного параметра.
Перенос существующих таблиц в решение со встроенной поддержкой
В этом примере показано, как перейти из существующего решения на основе триггеров в встроенную темпоральную поддержку. В этом примере предполагается, что текущее пользовательское решение разделяет текущие и исторические данные в две отдельные таблицы пользователей (ProjectTaskCurrent
и ProjectTaskHistory
).
Если существующее решение использует одну таблицу для хранения фактических и исторических строк, необходимо разделить данные на две таблицы перед этапами миграции, приведенными в следующем примере. Сначала удалите триггер из будущей темпоральной таблицы. Затем убедитесь, что PERIOD
столбцы не допускают значение NULL.
/* Drop trigger on future temporal table */
DROP TRIGGER ProjectCurrent_OnUpdateDelete;
/* Make sure that future period columns are non-nullable */
ALTER TABLE ProjectTaskCurrent
ALTER COLUMN [ValidFrom] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskCurrent
ALTER COLUMN [ValidTo] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskHistory
ALTER COLUMN [ValidFrom] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskHistory
ALTER COLUMN [ValidTo] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskCurrent ADD PERIOD
FOR SYSTEM_TIME([ValidFrom], [ValidTo]);
ALTER TABLE ProjectTaskCurrent SET (
SYSTEM_VERSIONING = ON (
HISTORY_TABLE = dbo.ProjectTaskHistory,
DATA_CONSISTENCY_CHECK = ON
)
);
Замечания
Ссылка на существующие столбцы в определении PERIOD
неявно изменяет generated_always_type
на AS_ROW_START
и AS_ROW_END
для этих столбцов.
Добавление PERIOD
выполняет проверку согласованности данных в текущей таблице, чтобы убедиться, что существующие значения для столбцов периода допустимы.
Мы настоятельно рекомендуем настроить SYSTEM_VERSIONING
с помощью DATA_CONSISTENCY_CHECK = ON
, чтобы обеспечить проверку согласованности данных для существующих данных.
Если предпочтительнее использовать скрытые столбцы, используйте команду ALTER TABLE [tableName] ALTER COLUMN [columnName] ADD HIDDEN;
.
Связанный контент
- Темпоральные таблицы
- Начало работы с системно-версионными темпоральными таблицами
- Управление хранением исторических данных в системных темпоральных таблицах
- Системные темпоральные таблицы с оптимизированными для памяти таблицами
- CREATE TABLE (Transact-SQL)
- Изменение данных в системной темпоральной таблице
- Запрос данных в системной темпоральной таблице
- Изменение схемы системной темпоральной таблицы
- Остановка системного версионирования в системной темпоральной таблице