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

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

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

注意

内存优化临时表仅在 SQL Server 和 Azure SQL 托管实例中可用。 内存优化表和临时表在 Azure SQL 数据库中独立可用。

概述

系统版本控制时态表自动保留完整的数据更改历史记录,并公开了一些实用的 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>;

当系统按照其内部计划执行数据刷新任务时,会触发同样的数据移动过程。