删除与截断


35

我试图对DELETETRUNCATE命令之间的差异有更深入的了解。我对内部结构的理解大致如下:

DELETE->数据库引擎从相关数据页和输入该行的所有索引页中查找并删除该行。因此,索引越多,删除时间越长。

TRUNCATE ->会简单地整体删除表的所有数据页,这使它成为删除表内容的更有效的选择。

假设以上正确(如果不正确,请纠正我):

  1. 不同的恢复模式如何影响每个语句?如果有任何作用
  2. 删除时,是扫描所有索引还是仅扫描行所在的索引?我假设所有索引都已扫描(而不查找?)
  3. 如何复制命令?SQL命令是否在每个订阅服务器上发送和处理?还是MSSQL比这更聪明?

2
在- 之前紧接-ing 的效用的此问题DELETE及其TRUNCATE答案中有一些相关信息。您也可以自己使用本答案中介绍的技术在日志中进行挖掘,以研究两个命令的效果。TRUNCATEDROP
Nick Chammas

1
此答案显示了DELETE和TRUNCATE操作的内部。该问题还显示了TRUNCATE更好地工作的特定情况。
孔夫子2012年

5
@idstam TRUNCATE可以回滚。尼克在对所链接问题的回答中提到了这一点
Mark Storey-Smith

截断需要“更改表”权限(从某种意义上说,截断是插入式替换,用于删除)。
crokusek

Answers:


58

DELETE->数据库引擎从相关数据页和所有输入该行的索引页中查找并删除该行。因此,索引越多,删除时间越长。

是的,尽管这里有两个选择。可以由执行基本表删除的同一运算符逐行从非聚集索引中删除行。这称为狭窄(或每行)更新计划:

每行删除

或者,非聚集索引删除可以由单独的运算符执行,每个非聚集索引一个。在这种情况下(称为广泛的或按索引的更新计划),将完整的操作集存储在工作表(紧急假脱机)中,然后对每个索引重播一次,通常按特定的非聚集索引的键显式排序以鼓励顺序操作。访问模式。

每个索引删除

TRUNCATE->简单地整体删除表的所有数据页,这使它成为删除表内容的更有效的选择。

是。 TRUNCATE TABLE有许多原因,因此效率更高:

  1. 可能需要更少的锁。截断通常仅需要在表级(和排它锁在每个单个架构修改锁程度解除分配)。删除可能会获得较低(行或页面)粒度的锁,以及对已分配的任何页面的排他锁。
  2. 只有截断才能保证从堆表中释放所有页面。即使指定了排他表锁定提示,删除操作也会在堆中留下空页(例如,如果为数据库启用了行版本隔离级别)。
  3. 截断总是被最小限度地记录(无论使用哪种恢复模型)。事务日志中仅记录页面重新分配操作。
  4. 如果对象的大小为128个范围或更大,则截断可以使用延迟丢弃。延迟删除意味着实际的重新分配工作由后台服务器线程异步执行。

不同的恢复模式如何影响每个语句?有什么作用吗?

删除总是完整记录(删除的每一行都记录在事务日志中)。如果恢复模型不是FULL,则日志记录的内容会有一些细微的差异,但是从技术上来说,这仍然是完整的日志记录。

删除时,是扫描所有索引还是仅扫描行所在的索引?我假设所有索引都已扫描(而不查找?)

删除索引中的一行(使用前面显示的窄或宽更新计划)始终是通过键进行的访问(查找)。扫描删除的每一行的整个索引将效率极低。让我们再次看一下前面显示的按索引更新计划:

广泛计划2

执行计划是需求驱动的管道:父运算符(左侧)通过一次请求子运算符来驱动子运算符执行工作。Sort运算符正在阻塞(它们必须在产生第一行之前消耗掉全部输入),但是它们仍受其父(索引删除)请求第一行的驱动。索引删除一次从完成的排序中拉出一行,从而更新每行的目标非聚集索引。

在广泛的更新计划中,您经常会看到基本表更新操作员将列添加到行流中。在这种情况下,“聚集索引删除”会将非聚集索引键列添加到流中。存储引擎需要此数据来找到要从非聚集索引中删除的行:

输出列表详细信息

如何复制命令?SQL命令是否在每个订阅服务器上发送和处理?还是SQL Server比这更智能?

使用事务复制或合并复制发布的表上不允许截断。复制删除的方式取决于复制的类型及其配置方式。例如,快照复制仅使用批量方法复制表的时间点视图-不会跟踪或应用增量更改。事务复制通过读取日志记录并生成适当的事务以将更改应用于订户而起作用。合并复制使用触发器和元数据表跟踪更改。

相关阅读:优化更改数据的T-SQL查询

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.