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

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

适用于内存优化表的系统版本控制时态表,为需要基于内存中 OLTP 工作负载收集的数据进行数据审计和时间点分析的场景,提供了一种经济高效的解决方案。

注释

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

Overview

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

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

用于内存优化表的系统版本化时序表提供高事务吞吐量和无锁并发性。 你可以通过使用内存内表存储当前数据(时间表)和基于磁盘的表存储历史数据来存储大量历史数据。 通过使用内部自动生成的、经过内存优化的暂存表来存储近期历史数据,并使 DML 操作能够通过本机编译代码执行,可以减少对 DML 操作的影响。

下图说明了此体系结构。

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

实施细节

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

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

  • 内存优化系统版本控制表的历史表必须基于磁盘,无论是你创建还是系统创建的。

  • 你可以在原生编译的 T-SQL 模块中使用仅影响当前内存中表的查询。 原生编译模块不支持该 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>;

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