SQLSERVER 的 truncate 和 delete 有区别吗?

[删除(380066935@qq.com或微信通知)]

更好的阅读体验请查看原文: https://www.cnblogs.com/huangxincheng/p/17104847.html

一:背景

1. 讲故事

在面试中我相信有很多朋友会被问到 truncate 和 delete 有什么区别 ,这是一个很有意思的话题,本篇我就试着来回答一下,如果下次大家遇到这类问题,我的答案应该可以帮你成功度过吧。

二:区别详解

1. 思考

从宏观角度来说, delete 是 DML 语句, truncate 是 DDL 语句,这些对数据库产生破坏类的语句肯定是要被 sqlserver 跟踪的,言外之意就是在某些场景下可以被回滚的,既然可以被 回滚,那自然就会产生 事务日志,所以从 事务日志 的角度入手会是一个好的办法。

为了方便测试,还是用上一篇的 post 表,创建好之后插入10条记录,参考sql如下:


DROP TABLE dbo.post;
CREATE TABLE post (id INT IDENTITY, content CHAR(1000) DEFAULT 'aaaaaa')

INSERT post DEFAULT VALUES 
GO 10

有了数据之后就可以通过 fn_dblog 函数从 MyTestDB.ldf 中提取事务日志来观察 delete 和 truncate 日志的不同点。

2. 观察 delete 的事务日志。

为了观察 delete 产生的日志,这里用 @max_lsn 记录一下起始点,参考sql如下:


DECLARE @max_lsn VARCHAR(100)
SELECT @max_lsn=[Current LSN] FROM fn_dblog(NULL,NULL)
DELETE FROM post;
SELECT * FROM fn_dblog(NULL,NULL) WHERE [Current LSN] >@max_lsn

从事务日志看, delete 主要做了两件事情。

  • 10 行 delete 记录删除

这里就有一个好奇的地方了,sqlserver 是如何执行删除操作的呢?要回答这个问题需要到数据页上找答案,参考sql如下:


DBCC IND(MyTestDB,post,-1)
DBCC PAGE(MyTestDB,1,240,2)

从图中可以得到如下两点信息, 至少在堆表下 delete 操作并没有删除 Page,第二个是 delete 记录删除只是将 slot 的指针 抹0

有些朋友可能要问,为什么还有对 PFS 的操作呢?很简单它就是用来记录当前页面的 占用空间比率 的,可以看下我的上一篇文章。

3. 观察 truncate 的事务日志。

delete 原理搞清楚之后,接下来看下 truncate 做了什么?参考sql 如下:


DROP TABLE dbo.post;
CREATE TABLE post (id INT IDENTITY, content CHAR(1000) DEFAULT 'aaaaaa')

INSERT post DEFAULT VALUES 
GO 10

DECLARE @max_lsn VARCHAR(100)
SELECT @max_lsn=[Current LSN] FROM fn_dblog(NULL,NULL)
TRUNCATE TABLE dbo.post
SELECT [Current LSN],Operation,Context,AllocUnitName FROM fn_dblog(NULL,NULL) WHERE [Current LSN] >@max_lsn

从图中可以看到,truncate 主要是对 IAM, PFS, GAM 三个空间管理数据页做了修改,并没有涉及到 PAGE 页,那就有一个疑问了,我的PAGE页还在吗?可以用 DBCC IND 看下。

我去,truncate 操作居然把我的 PAGE 页给弄丢了,它是怎么实现的呢? 要想找到答案,大家可以想一想, truncate 是一个 DDL 语句,为了快速释放表数据,它干脆把 postpage 的关系给切断了,如果大家有点懵,画个图大概就是下面这样。

为了验证这个结论,可以用 DBCC PAGE 直接导出 240 号数据页,观察下是不是表中的数据,不过遗憾的是,这个数据页已不归属 post 表了。。。

接下来又得回答另外一个问题,sqlserver 是如何切断的? 这里就需要理解 GAM 空间管理机制。

三:GAM 空间管理

1. 基本原理

GAM 是用来跟踪 区分配 状态的数据页,它是用一个 bit 位跟踪一个 , 在数据库中一个区表示 连续的8个数据页,在 GAM 数据页中,用 1 表示可分配的初始状态,用 0 表示已分配状态,可能大家有点懵,我再画个简图吧。

为了让大家眼见为实,还是用 post 给大家做个演示。


DROP TABLE dbo.post;
CREATE TABLE post (id INT IDENTITY, content CHAR(1000) DEFAULT 'aaaaaa')
INSERT post DEFAULT VALUES 
GO 10

DBCC TRACEON(3604)
DBCC IND(MyTestDB,post,-1)

从图中可以看到,post 表分配的数据页是 240241 号,对应的区号就是 240/8 + 1 = 31,因为 GAM 是用 1bit 来跟踪一个区,所以理论上 GAM 页面偏移 31bit 的位置就标记了该区的分配情况。

这么说可能大家又有点懵,我准备用 windbg 来演示一下,首先大家要记住 GAM 是 mdf 文件中的第三个页面,用 2 表示, 前两个分别是 文件头 和 PFS 页,关于页面的首地址可以用 DBCC PAGE(MyTestDB,1,2,2) 导出来。


0:078> dp 00000009009F8000 +0x60
00000009`009f8060  00000000`005e0000 00000000`00000000
00000009`009f8070  00000000`00000000 00000000`00000000
00000009`009f8080  00000000`00000000 00000000`00000000
00000009`009f8090  00000000`00000000 00000000`00000000
00000009`009f80a0  00000000`00000000 00000000`00000000
00000009`009f80b0  00000000`00000000 00000000`00000000
00000009`009f80c0  d0180000`00001f38 ffffffff`ffffffd1
00000009`009f80d0  ffffffff`ffffffff ffffffff`ffffffff

从输出内容看,那个 0x1f38 就是 bitmap 数组的长度,后面就是 bit 的占用情况,因为在 31 bit 上,我们观察一个 int 就好了,输出如下:

从图中可以看到,全部都是 0 也就说明当前都是分配状态,如果是 1 表示未分配,接下来把 post 给 truncate 掉再次观察 GAM 页。


TRUNCATE TABLE dbo.post;
DBCC PAGE(MyTestDB,1,2,2)

输出如下:


0:117> dp 00000009009F8000+0x60
00000009`009f8060  00000000`005e0000 00000000`00000000
00000009`009f8070  00000000`00000000 00000000`00000000
00000009`009f8080  00000000`00000000 00000000`00000000
00000009`009f8090  00000000`00000000 00000000`00000000
00000009`009f80a0  00000000`00000000 00000000`00000000
00000009`009f80b0  00000000`00000000 00000000`00000000
00000009`009f80c0  d0184000`00001f38 ffffffff`ffffffd1
00000009`009f80d0  ffffffff`ffffffff ffffffff`ffffffff

对比之后会发现由原来的 000000001f38 变成了 400000001f38,可以用 .format 来格式化下。

从图中看 31bit 跟踪的第 31 号区被回收了,也就验证了真的切断了联系。

同样的道理 PFS 偏移的 0n240 位置跟踪的这个页面也是被释放状态。

四:总结

总的来说,delete 操作是将数据页中的每个 slot 指针一条一条的擦掉,每次擦除都会产生一条事务日志,所以对海量数据进行 delete 会产生海量的事务日志,导致你的 日志文件 暴增。而 truncate 是直接切断 post 和 page 的联系,只需要修改几个空间管理页的 bit 位即可。

最后的建议是如果要清空表数据,建议用 truncate table

玻璃钢生产厂家广东玻璃钢雕塑批发人物雕塑玻璃钢蜘蛛侠雕塑正阳玻璃钢雕塑加工厂家常州人物玻璃钢雕塑定制富阳区玻璃钢雕塑价格夺艺雕塑玻璃钢人物订做关于店庆商场梯口美陈吴川玻璃钢座椅雕塑郑州佛像玻璃钢雕塑批发普陀区定制玻璃钢雕塑推荐石家庄玻璃钢雕塑批发大玻璃钢花盆价格行情热门玻璃钢动物雕塑铸造校园玻璃钢景观雕塑厂家玻璃钢人像雕塑翻新过程高档玻璃钢花盆生产陕西玻璃钢仿铜雕塑晋宁玻璃钢仿真雕塑北京火烈鸟玻璃钢雕塑生产厂家河北商场美陈生产企业梅河口玻璃钢雕塑厂家商场美陈方案文章时尚商场美陈卢氏玻璃钢雕塑厂家广州环保玻璃钢雕塑价位宁德玻璃钢卡通雕塑佛山发光动物玻璃钢雕塑玻璃钢橱窗美陈雕塑黑龙江玻璃钢桃子雕塑新乡卡通玻璃钢雕塑公司香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化