表上的DELETE操作

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:

在今天的文章里,我想给你快速展示下当我们从表里删除记录时,在SQL Server里发生了什么。首先我们来创建一个简单的表,在8KB的页上刚好能插入4条记录。 

复制代码
1 -- Create a simple table where 4 records fit onto 1 page
2 CREATE TABLE TestTable
3 (
4     Col1 INT IDENTITY(1, 1),
5     Col2 CHAR(2000)
6 )
7 GO
复制代码

接下来我们插入4条记录,这样的话一个页刚好全部填满。

复制代码
 1 -- Insert 4 records
 2 INSERT INTO TestTable VALUES
 3 (
 4     REPLICATE('1', 2000)
 5 ),
 6 (
 7     REPLICATE('2', 2000)
 8 ),
 9 (
10     REPLICATE('3', 2000)
11 ),
12 (
13     REPLICATE('4', 2000)
14 )
15 GO
复制代码

为了研究我们堆表的细节,我们使用DBCC PAGE命令来倾倒出分配的页面。因此我们还要启用3604跟踪标志,这样的话SQL Server从DBCC PAGE命令直接把结果输入到我们SSMS的会话窗口:

1 -- Enable the Trace Flag 3604
2 DBCC TRACEON(3604)
3 GO

我们可以使用DBCC IND命令返回所有分配给指定表或索引的页: 

1 -- Retrieve all pages of the table
2 DBCC IND(DataModifications, TestTable, -1)
3 GO

从输出可以看到,2个页属于我们的表:数据页本身,还有IAM(索引分配图(index allocation map))页。

我这里的页号是118,通过DBCC PAGE命令倾倒出页面: 

1 -- Dump out one specific page
2 DBCC PAGE (DataModifications, 1, 118, 2)
3 GO

当你使用选项2的第3个参数倾倒,SQL Server返回你16进制的页倾倒,包括在页尾所谓的行偏移数组(Row Offset Array),不以任何方式影响数据。

行偏移数组指向在页上的物理位置,即每条记录存储的地方。第1条记录总是直接存储在页头偏移量96(0x60h)的地方。你也会看到,行偏移数组是逆向增长的。现在让我们从表里删除第2条记录: 

1 -- Delete a record from the table
2 DELETE FROM TestTable
3 WHERE Col1 = 2
4 GO

通常这里你会期待记录从页里删除。但事实上并不如此:当你再次执行DBCC PAGE命令时,你会看到在页上老记录的内容还是可以看到。在DELETE操作期间,SQL Server唯一做的是,在页尾行偏移数组里,对应的槽无效了。

如你所见,第2个槽的偏移量是0x0,这是无效的,意味着我们的记录被删除了。在页开始部分,你总会找到96 bytes的页头。现在让我们从表里删除其它的剩余3条记录。 

1 -- Delete all the remaining records from the table
2 DELETE FROM TestTable
3 GO

当你再次用DBCC PAGE命令查看页,你会看到页全部内容还是没改变:每条记录的每个数据在页上还是物理存在的!但是在行偏移数据里每条记录都指向偏移量0x0,这意味着每条记录都被删除。这与你的表是否使用了聚集索引无关——老数据在页上一直存在。
现在的问题是,SQL Server什么时候会初始化页?当你现在插入新的记录,SQL Server会覆盖页的原始内容。但在我们的情况里,这只是物理部分,第1条记录存储的位置。你还是能看到其它“删除”的记录内容。当你在页尾看下行偏移数组,你会看到它已被SQL Server完全初始化了,也意味着你在行偏移数组里你现在只有1个槽了:

当你下次授权给程序sysadmin特权时,要考虑下这个情况了。使用合适的命令,这些程序还是能看到已经“删除”的数据。



本文转自Woodytu博客园博客,原文链接:http://www.cnblogs.com/woodytu/p/4637157.html,如需转载请自行联系原作者

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
1月前
|
SQL 监控 关系型数据库
避免锁表:为Update语句中的Where条件添加索引字段
在一个灰度环境中,某业务创建数据时出现异常延迟,原本以为是第三方接口问题,但日志显示接口响应正常。进一步排查发现,工单表的SQL插入操作因另一个业务的无索引UPDATE操作阻塞。具体问题在于UPDATE语句的where子句涉及字段缺失索引,导致锁表并影响并发性能。通过复现问题并为相关字段添加索引,解决了阻塞问题。重要的是,在编写UPDATE语句时要注意Where条件字段的索引,以优化查询并减少锁表影响。
61 6
避免锁表:为Update语句中的Where条件添加索引字段
|
1月前
|
SQL 关系型数据库 MySQL
|
1月前
|
存储 关系型数据库 MySQL
Mysql数据库清空表 truncate和delete
Mysql数据库清空表 truncate和delete
35 0
|
1月前
|
关系型数据库 索引
select for update有什么含义,会锁表还是锁行还是其他。
select for update有什么含义,会锁表还是锁行还是其他。
|
1月前
|
SQL
DML(insert与delete)
DML(insert与delete)
25 0
|
9月前
数据更新语句INSERT语句、UPDATE语句、DELETE语句等,用于向数据表中插入、更新或删除数据。示例
数据更新语句INSERT语句、UPDATE语句、DELETE语句等,用于向数据表中插入、更新或删除数据。示例
65 1
|
存储 索引
清空表时优先使用truncate
清空表时优先使用truncate
|
SQL 数据处理 数据库
DML 之 DELETE|学习笔记
快速学习 DML 之 DELETE
52 0
DML 之 DELETE|学习笔记
|
存储 索引
十、清空表时优先使用truncate
十、清空表时优先使用truncate
93 0
|
SQL 存储 缓存
执行update语句,用没用到索引,区别大吗?
我们都知道,当执行 select 查询语句时,用没用到索引区别是很大的,若没用到索引,一条 select 语句可能执行好几秒或更久,若使用到索引则可能瞬间完成。那么当执行 update 语句时,用没用到索引有什么区别呢,执行时间相差大吗?本篇文章我们一起来探究下。
367 0