系统版本控制时态表与内存优化表

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

用于内存优化表的系统版本控制时态表旨在为以下情形提供经济高效的解决方案:需要基于使用内存中 OLTP 工作负载收集的数据进行数据审核和时间点分析

概述

系统版本控制时态表自动保留完整的数据更改历史记录,并公开了一些实用的 Transact-SQL 扩展,以便用于时间点分析。 在典型方案中,即使是不定期查询的数据历史记录,也会保留很长时间(数月甚至数年)。

可以在不同的环境中要求进行数据审核和基于时间的分析,尤其是在处理极其大量的请求并且使用内存中 OLTP 技术的 OLTP 系统中。 但是,在临时方案中使用内存优化表极具挑战性,因为所生成的大量历史数据通常会超出可用 RAM 内存的限制。 与此同时,使用 RAM 来存储因变陈旧而较少访问的只读历史数据并不是最佳的解决方案。

内存优化表的系统版本控制时态表旨在提供较高的事务吞吐量和无锁并发。 这些时态表能使用内存中表来存储当前数据(时态表)以及使用基于磁盘的表来存储历史数据,从而存储大量历史记录数据。 通过使用自动生成的内部内存优化临时表来存储最新历史记录并支持从本机编译的代码执行 DML,可以降低对 DML 操作的影响。

下图对此结构进行了说明。

临时内存中体系结构示意图。

实现详细信息

创建系统版本控制内存优化表时,请注意以下注意事项。 有关语法选项和示例,请参阅 CREATE TABLE

  • 只有持久内存优化表才能进行系统版本控制 (DURABILITY = SCHEMA_AND_DATA)。

  • 无论创建者是最终用户还是系统,用于内存优化系统版本控制表的历史记录表都必须基于磁盘。

  • 只影响当前内存中表的查询可用于本机编译的 T-SQL 模块。 本机编译的模块中不支持使用 FOR SYSTEM TIME 子句的临时查询。 支持在即席查询和非本机模块中将 FOR SYSTEM TIME 子句与内存优化表一起使用。

  • SYSTEM_VERSIONING = ON 时,系统将自动创建内部内存优化临时表来接受最新的系统版本控制更改,这些更改是对当前内存优化表执行更新和删除操作时产生的结果。

  • 内部内存优化临时表中的数据将通过异步数据刷新任务定期移动到基于磁盘的历史记录表。 此数据刷新机制将内部内存缓冲区中父对象的内存消耗控制在 10% 以下。 可以通过查询 sys.dm_db_xtp_memory_consumers 并汇总内部内存优化时态表和当前时态表的数据,来跟踪内存优化系统版本控制临时表的内存总消耗。

  • 可以通过运行 sp_xtp_flush_temporal_history 来手动执行数据刷新。

  • SYSTEM_VERSIONING = OFF 时,或者通过添加、删除或更改列来修改系统版本控制表的架构时,内部临时缓冲区的全部内容将移动到基于磁盘的历史记录表中。

  • 历史数据查询在快照隔离级别下非常有效,并且始终返回内存中临时缓冲区与基于磁盘的表之间的并集(无重复项)。

  • 从内部更改表架构的 ALTER TABLE 操作必须执行数据刷新,这可能会延长该操作的持续时间。

内部内存优化临时表

系统创建内部内存优化临时表来优化 DML 操作。

  • 表名称采用以下格式生成:Memory_Optimized_History_Table_<object_id>,其中 <object_id> 是当前时态表的标识符。

  • 该表在当前时态表的架构上另加一个 bigint 列。 此额外列保证了移动到内部历史记录缓冲区的行的唯一性。

  • 此额外列采用以下名称格式:Change_ID[<suffix>],其中 <suffix> 可以在表已有 Change_ID 列的情况下选择性地进行添加。

  • 系统版本控制内存优化表的行大小上限因临时表中的额外 bigint 列而减去 8 个字节。 新的大小上限现在为 8,052 字节。

  • 内部内存优化临时表不显示在 SQL Server Management Studio 的对象资源管理器中。

  • 你可以在 sys.internal_tables 中找到此表的相关元数据及其与当前时态表的关联。

数据刷新任务

数据刷新是一项定期激活的任务,用于检查是否有任何内存优化表满足数据移动的基于内存大小的条件。 内部临时表的内存消耗达到当前时态表内存消耗的 8% 时,将启动数据移动。

数据刷新任务定期激活,其计划因现有工作负荷而异。 对于繁重的工作负载,任务每 5 秒运行一次。 对于较轻的工作负载,频率将增加到每分钟允许一次。 每个需要清理的内部内存优化临时表将生成一个线程。

数据刷新会从内存中内部缓冲区删除早于当前运行的最早事务的所有记录,以便将这些记录移动到基于磁盘的历史记录表。

可以运行 sp_xtp_flush_temporal_history 和指定架构和表名称来执行数据刷新:

EXEC sys.sp_xtp_flush_temporal_history <schema_name>, <object_name>;

这将像系统按内部计划调用数据刷新任务时一样,调用相同的数据移动进程。