前言

之前写过一篇, 但那个时候还没有开始用, 现在是要用了, 所以翻新一下呗.

SQL server temporal table 学习笔记

主要参考:

官网 Temporal tables

[译]SQL SERVER 2016 – Temporal Tables

SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Temporal Table (历史表)

用处

Find back history

Temporal table 会做多一个 history table, 把所有修改/删除的资料存起来, 所以任何数据都不会丢失. 要找回也比较容易.

Time Travel

任何修改/删除的资料都会有时间记入, 通过 build-in 的 query 语句, 我们可以快速查询某个时间点的数据. (俗称 – 时间旅行)

参考:

Temporal table usage scenarios

代价

1.会拉慢 update, delete 执行, 因为执行多了一个把资料 insert to history table 的动作.

2.会增加 disk space

3. 维护成本, 由于 history table 的 Design 和 temporal table 是一致的, 所以我们也要确保 history data 符合 table design,

最常见的例子是 nullable to not null, history data 的 null 都要 update 成 not null, 而且无法直接修改 history table 哦, 需要 off versioning 等等

与之相关

Temporal table 经常和 Change Data Capture (CDC), Change Tracking (CT), Event Sourcing, Soft Delete, Audit Trail 一起讨论.

我对 CDC, CT, Event Sourcing 不太清楚, 就不说了.

Soft Delete 应该算是一种比较简单实现的 find back history 方案. 与 Temporal Table 比的话, 区别是

Temporal Table 是 SQL Server build-in 的方案, 有特定的 query 语句, 整个 update, delete 过程都是封装的.

Soft Delete 则只是在简单的 SQL 语句上做了一些规则去实现一部分 Temporal Table 的功能而已. Soft Delete 的优势只有一个就是它简单.

Temporal Table 可以帮助解决一些 Audit Trail 的问题, 如果我们的 tracking 范围只是针对数据改动的话, 它是 ok 用的, 但一般上我们会需要 tracking 整个 application 的使用, 而不仅仅是数据库的改动.

参考:

SQL Server Temporal Tables vs Change Data Capture vs Change Tracking - part 1

SQL Server Temporal Tables vs Change Data Capture vs Change Tracking - part 2

SQL Server Temporal Tables vs Change Data Capture vs Change Tracking - part 3

Event sourcing vs SQL Server Temporal Tables

历史

Temporal Table 是 2011 年才有的规范, SQL Server 实现是在 2016 版本.

How It Work

当我们创建一个 Temporal Table 时, SQL Server 会同时创建一个对应的 history table. 每一条 row 都需要记入 2 个 columns, SysStartTime 和 SysEndTime (Time Travel 就靠这个完成的)

当 insert 数据时, SysStartTime 就是当下, SysEndTime 是 9999 年. (insert 数据对 history table 是不会有任何作用的, 只有 update 和 delete 才会)

当 update 数据时, 先把要 update 的 row clone to the history table, 然后设置 SysEndTime 为当下, 接着 update row 同时把 SysStartTime 设置成当下. (注: 不管值是否有真的变化, 只要 update 语句执行, history table 就会多一条 row)

当 delete 数据时, 先把要 delete 的 row clone to the history table, 然后设置 SysEndTime 为当下, 接着 delete row.

query 的时候通过 join history table + 过滤 SysStartTime 和 SysEndTime 就可以拿到任何时间点上的数据了.

上面这个过程都是封装起来的, 我们基本上就是像用普通表一样执行 Create, Update, Delete 就可以了. 而在 Select 的时候会有一些特制的 query 语句来查询 history table.

Naming Conversion

SysStartTime (SQL Server doc) = ValidFrom (SQL Server, Ef Core docs) = PeriodStart (EF core default docs)

SysEndTime (SQL Server doc) = ValidTo (SQL Server, Ef Core docs) = PeriodEnd (EF core default docs)

实战

创建 Temporal Table

CREATE TABLE dbo.Person
(
Id int NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
Name nvarchar(120) NOT NULL,
Age int NOT NULL,
SysStartTime datetime2 GENERATED ALWAYS AS ROW START,
SysEndTime datetime2 GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.PersonHistory));

关键就是多了 SysStartTime, SysEndTime 然后 SYSTEM_VERSIONING = 0, 附上 history table 名字就可以了

出来后长这样, Person table 的 icon 换了, 里头也多了一个 PersonHistory table

Insert data

INSERT INTO Person (Name, Age) VALUES ('xin yao', 10);
SELECT * FROM Person;
SELECT * FROM PersonHistory;

Insert data 不会对 history table 有任何副作用.

Update Data

UPDATE Person SET AGE = 15 WHERE Id = 1;
SELECT * FROM Person;
SELECT * FROM PersonHistory;

History table 有历史记入了. 它们的时间也更新了.

Delete Data

DELETE FROM Person WHERE Id = 1;
SELECT * FROM Person;
SELECT * FROM PersonHistory;

History table 又多了一条, 时间也更新了

Select data

全部资料调出来

SELECT * FROM Person FOR SYSTEM_TIME ALL; 

调出某个时间点的资料

SELECT * FROM Person FOR SYSTEM_TIME AS OF '2021-10-19 06:00:39.2906582';

这个就有点像我们 git checkout 到某个 commit 那样.

它的 WHERE 语句时:

SysStartTime <= date_time AND SysEndTime > date_time

调出某个期间的资料

SELECT * FROM Person FOR SYSTEM_TIME FROM '2021-10-19 05:59:11.5214221' TO '2021-10-19 06:00:39.2906583';
SELECT * FROM Person FOR SYSTEM_TIME BETWEEN '2021-10-19 05:59:11.5214221' AND '2021-10-19 06:00:39.2906583';

这 2 个其实很像, 所以一起讲吧.

它的 WHERE 语句是:

SysStartTime < end_date_time AND SysEndTime > start_date_time (FROM, TO)

SysStartTime <= end_date_time AND SysEndTime > start_date_time (BETWEEN AND)

调出某个期间内的资料

SELECT * FROM Person FOR SYSTEM_TIME CONTAINED IN ('2021-10-19 05:59:11.5214221','2021-10-19 06:00:39.2906583');

它的 WHERE 语句是:

SysStartTime >= start_date_time AND SysEndTime <= end_date_time

Drop Temporal Table

先 OFF, 然后分别删除 2 个 table

ALTER TABLE Person SET (SYSTEM_VERSIONING = OFF);
DROP TABLE Person;
DROP TABLE PersonHistory;

创建 for existing table

参考: Alter non-temporal table to be a system-versioned temporal table

目前我没有这个需求, 所以暂时不研究了, 因为它有一些 important remark 要 take care, 但我看不太懂.

常见问题和局限

Temporal table 其实有许多局限性, 所以大部分人都不建议把所有 Table 设置成 Temporal Table. Why would all tables not be temporal tables by default?

参考: Temporal Table Considerations and Limitations

Timezone

SysStartTime, SysEndTime 用的是 datetime(7) UTC 时间. 这个对查询不友好.

解决方法看这里

/*Add offset of the local time zone to current time*/
DECLARE @asOf DATETIMEOFFSET = GETDATE() AT TIME ZONE 'Pacific Standard Time'
/*Convert AS OF filter to UTC*/
SET @asOf = DATEADD (MONTH, -9, @asOf) AT TIME ZONE 'UTC'; SELECT
EmployeeID
, Name
, Position
, Department
, [Address]
, [AnnualSalary]
, SysStartTime AT TIME ZONE 'Pacific Standard Time' AS SysStartTimePT
, SysEndTime AT TIME ZONE 'Pacific Standard Time' AS SysEndTimePT
FROM Employee
FOR SYSTEM_TIME AS OF @asOf where EmployeeId = 1000;

Nullable to Not Null

History table 需要更新, 确保符合 Temporal table design, 类似下面这样.

SQL Server – Temporal Table 时态表的更多相关文章

  1. sql server truncate table 删除表数据限制条件

    truncate 注释 注释TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行.但 TRUNCATE TABLE 比 DELETE 速度快 ...

  2. 获得sql server的table的表结构 -- 转到word中

    SQL语句: select syscolumns.name,systypes.name,syscolumns.length from syscolumns  join sysobjects on sy ...

  3. Sql Server系列:数据表操作

    表是用来存储数据和操作数据的逻辑结构,用来组织和存储数据,关系数据库中的所有数据都表现为表的形式,数据表由行和列组成.SQL Server中的数据表分为临时表和永久表,临时表存储在tempdb系统数据 ...

  4. 查看SQL Server被锁的表以及如何解锁

    锁定数据库的一个表的区别 SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除 SELECT * FROM table WITH (TABLOCK ...

  5. 清空SQL Server数据库中所有表数据的方法(转)

    清空SQL Server数据库中所有表数据的方法 其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间可能形成相互约束关系,删除操作可能陷入 ...

  6. SQL Server跨库复制表数据错误的解决办法

    SQL Server跨库复制表数据的解决办法   跨库复制表数据,有很多种方法,最常见的是写程序来批量导入数据了,但是这种方法并不是最优方法,今天就用到了一个很犀利的方法,可以完美在 Sql Serv ...

  7. MS SQL SERVER 中的系统表

    MS SQL SERVER 中的系统表 序号 名称 说明 备注 1 syscolumns 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行.   2 syscomments 包含每 ...

  8. 清空SQL Server数据库中所有表数据的方法

    原文:清空SQL Server数据库中所有表数据的方法 其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间可能形成相互约束关系,删除操作可 ...

  9. Sql server中如何将表A和表B的数据合并(乘积方式)

    sql server中如何将表A 和表B的数据合并成乘积方式,也就是说表A有2条数据,表B有3条数据,乘积后有6条数据, 这就要用到sql中的笛卡尔积方式了 1.什么是笛卡尔积 笛卡尔积在SQL中的实 ...

  10. [转]查看SQL Server被锁的表以及如何解锁

    本文转自:https://www.cnblogs.com/shy1766IT/p/6225694.html 锁定数据库的一个表的区别 SELECT * FROM table WITH (HOLDLOC ...

随机推荐

  1. CentOS 8安装docker

    1.查看Linux内核(Docker最低支持CentOS 7 64位 内核3.10) uname -a 2.安装docker(输入yes,然后等待-) yum install docker 3.启动d ...

  2. Linux如何安装PHPMyAdmin

    1,我们要以root帐号登入 . 2,PHP支持模块安装.在CentOS操作系统安装完毕后,其实PHP支持模块并没有安装上去,如果想使用PhpMyAdmin,首先需要安装PHP支持模块,我们需要两个P ...

  3. [oeasy]python0096_游戏娱乐行业_雅达利_米洛华_四人赛马_影视结合游戏

    游戏娱乐行业 回忆上次内容 游戏机行业从无到有 雅达利 公司 一枝独秀 并且带领 行业 发展起来 雅达利公司 优秀员工 乔布斯 在 朋友 帮助下完成了<pong> Jobs 黑了 Woz ...

  4. oeasy教您玩转vim - 42 - # 剪切进入

    ​ 剪切进入 回忆上节课内容 上次我们了解到了各种寄存器 :reg 无名寄存器"" 数字寄存器"0-"9 行内删除专用寄存器"- 指定寄存器" ...

  5. 手写数字识别-使用TensorFlow构建和训练一个简单的神经网络

    下面是一个具体的Python代码示例,展示如何使用TensorFlow实现一个简单的神经网络来解决手写数字识别问题(使用MNIST数据集).以下是一个完整的Python代码示例,展示如何使用Tenso ...

  6. LRZ

    1.在平面直角坐标系中,已知点 \(A(-2,2).B(3,4).C(0,1)\),直线 \(y=kx+b\) 过点 \(C\) 且与线段 \(AB\) 有交点,则 \(k\) 的取值范围是_____ ...

  7. app接口测试

    app接口测试 一,app请求服务器端接口和web页面请求服务器端接口有什么区别? 1,大多数项目如果有app的话,而且web端和app端的页面显示结构已经功能都相似,调用的后台接口也是一样的. 2, ...

  8. Jmeter函数助手15-FiletoString

    FiletoString函数用于一次读取整个文件值. 输入文件的全路径:填入文件路径 File encoding if not the platform default (opt):读取文件的编码格式 ...

  9. 《Python数据可视化之matplotlib实践》 源码 第一篇 入门 第一章

    最近手上有需要用matplotlib画图的活,在网上淘了本实践书,发现没有代码,于是手敲了一遍,mark下. 第一篇    第一章 图1.1 import matplotlib.pyplot as p ...

  10. 使用GPU计算时,单精度float32类型和半精度float16类型运算效率的区别

    最近在看资料时发现写着使用float16 半精度类型的数据计算速度要比float32的单精度类型数据计算要快,因为以前没有考虑过数据类型对计算速度的影响,只知道这个会影响最终的计算结果精度.于是,好奇 ...