时态表注意事项和限制

适用于:SQL Server 2016 (13.x) 及更高版本 Azure SQL 数据库 Azure SQL 托管实例

由于系统版本控制的特性,在使用时态表时,有一些应考虑的注意事项和限制:

  • 时态表必须有已定义的主键,以便将当前表的记录和历史记录表的记录关联起来。 历史记录表不能有已定义的主键。

  • 用于记录 ValidFromValidTo 值的 SYSTEM_TIME 时间段列必须使用数据类型 datetime2 进行定义。

  • 时态语法适用于存储在数据库中本地存储的表或视图。 对于远程对象(如链接服务器上的表或外部表),不能直接在查询中使用 FOR 子句或句点谓词。

  • 如果历史记录表的名称在历史记录表创建期间指定,则必须指定架构和表的名称。

  • 默认情况下,历史记录表是经过 PAGE 压缩的。

  • 如果当前表已分区,则历史记录表在默认文件组上创建,因为不会自动将分区配置从当前表复制到历史记录表。

  • 时态表和历史记录表不能使用 FileTable 或 FILESTREAM。 FileTable 和 FILESTREAM 允许在 SQL Server 外部进行数据操作,因此无法保证系统版本控制。

  • 不能将节点或边缘表创建为时态表或将其更改为时态表。

  • 尽管时态表支持 blob 数据类型,如 (n)varchar(max)、varbinary(max)、(n)text 和 image,但由于其大小,会导致产生巨大的存储成本,并可能对性能产生影响。 因此在设计系统的过程中,应慎重使用这些数据类型。

  • 必须在当前表所在的数据库中创建历史记录表。 不支持对链接服务器的时态查询。

  • 历史记录表不能有约束(主键、外键、表或列约束)。

  • 时态查询(使用 FOR SYSTEM_TIME 子句的查询)的顶部不支持索引视图。

  • 在系统版本控制的时态表中,联机选项 (WITH (ONLINE = ON) 对 ALTER TABLE ALTER COLUMN 不起任何作用。 无论为 ALTER 选项指定的值是什么,ONLINE 列都不会作为联机操作执行。

  • INSERTUPDATE 语句无法引用 SYSTEM_TIME 时间段列。 已阻止将值直接插入这些列的尝试。

  • SYSTEM_VERSIONINGON 时,不支持 TRUNCATE TABLE

  • 不允许直接修改历史记录表中的数据。

  • 不允许针对当前表执行 ON DELETE CASCADEON UPDATE CASCADE。 换言之,当时态表引用外键关系中的表时(对应于 sys.foreign_key 中的 parent_object_id),将不允许使用 CASCADE 选项。 要解除此限制,使用应用程序逻辑或 after 触发器,在主键表中进行删除时保持一致性(对应于 sys.foreign_key 中的 referenced_object_id)。 如果主键表是时态表,而引用表为非时态表,则不存在此类限制。
  • 在当前表或历史记录表上均不允许使用 INSTEAD OF 触发器,以避免导致 DML 逻辑失效。 仅在当前表上允许 AFTER 触发器。 这些触发器在历史记录表上会被阻止,以便避免导致 DML 逻辑失效。

  • 复制技术的使用受到限制:

    • 可用性组:完全受支持

    • 变更数据捕获和更改跟踪:仅当前表支持

    • 快照和事务复制:仅支持未启用时态的单个发布服务器和已启用时态的单个订阅服务器。 不支持使用多个订阅服务器,因为这可能会由于依赖本地系统时钟而导致时态数据不一致。 在这种情况下,发布服务器用于 OLTP 工作负载,而订阅服务器用于卸载报表(包括 AS OF 查询)。 启动后,分发代理打开在其停止前一直保持打开状态的事务。 ValidFromValidTo 填充到分发代理启动的第一个事务的开始时间。 如果对应用程序或组织而言,如果必须向 ValidFromValidTo 填充一个接近于当前系统时间的时间,那么按计划运行分发代理可能比连续运行默认行为更可取。 有关详细信息,请参阅时态表使用方案

    • 合并复制: 不支持临时表

  • 定期查询仅影响当前表中的数据。 若要查询历史记录表中的数据,必须使用临时查询。 有关详细信息,请参阅查询系统版本控制时态表中的数据

  • 最佳索引编制策略会包括当前表上的聚集列存储索引和/或 B 树行存储索引,以及历史记录表上的聚集列存储索引,旨在优化存储大小和性能。 如果创建/使用自己的历史记录表,强烈建议创建此类型的索引,索引应包含以时间段列的结尾为开头的时间段列。 此索引以加快时态查询和数据一致性检查。 默认历史记录表具有基于时间段列(结束、开始)创建的聚集行存储索引。 建议至少应使用非聚集行存储索引。

  • 创建历史记录表后,不会将下列对象/属性从当前表复制到历史记录表:

    • 时间段定义
    • 标识定义
    • 索引
    • 统计信息
    • 检查约束
    • 触发器
    • 分区配置
    • 权限
    • 行级别安全性谓词
  • 在历史记录表链中,无法将历史记录表配置为当前表。

注意

文档在提到索引时一般使用 B 树这个术语。 在行存储索引中,数据库引擎实现了 B+ 树。 这不适用于列存储索引或内存优化表上的索引。 有关详细信息,请参阅 SQL Server 以及 Azure SQL 索引体系结构和设计指南