正如你的标题所说 - 如果你正在寻找最快的方法,那么你应该截断表格。
TRUNCATE TABLE [dbo].[mytable]
截断表有the following advantages:
与DELETE语句相比,TRUNCATE TABLE有以下几点
优点:
DELETE 语句一次删除一行并记录一个条目
在每个已删除行的事务日志中。 TRUNCATE TABLE 删除
通过释放用于存储表数据的数据页来获取数据
并且只在事务日志中记录页面释放。
当使用行锁执行 DELETE 语句时,每一行在
该表被锁定以进行删除。 TRUNCATE TABLE 总是锁定
表(包括架构 (SCH-M) 锁)和页,但不是每一行。
在执行 DELETE 语句后,表仍然可以包含
空白页。例如,堆中的空页不能被释放
至少没有排他(LCK_M_X)表锁。如果删除
操作不使用表锁,表(堆)将包含
许多空白页。对于索引,删除操作可以留空
后面的页面,尽管这些页面将被快速释放
后台清理进程。
TRUNCATE TABLE 删除表中的所有行,但表结构
并且它的列、约束、索引等仍然存在。删除
表定义除了它的数据,使用 DROP TABLE
声明。
如果表包含标识列,则该列的计数器
重置为为列定义的种子值。如果没有种子
定义时,使用默认值 1。要保留身份计数器,
请改用 DELETE。
虽然截断也会重置标识,所以如果您需要保留它,您应该先获取标识符(从表中编写脚本),然后在截断后将表设置回该标识符。或者,您可以只编写表格的脚本,删除它并重新创建它。
或者,您可以使用以下命令轻松切换表数据
--May need to script out table if you have things like compression.
select TOP 0 * into mytable_old from mytable;
ALTER TABLE mytable SWITCH TO mytable_old;
DROP TABLE mytable_old;
切换数据是一种元数据更改,实际上没有数据在磁盘上移动,因此这通常是一个相当快的(假设表上没有阻塞)操作和非常少的 I/O。删除表当然会像往常一样招致 I/O 惩罚。
最后 - 如果由于某种原因您在表上有 A BUNCH 锁,您可能希望慢慢地从表中删除记录。这并不快,但是当我使用它时,它会将阻塞保持在最低限度,因为删除窗口很快。不过,这会将更多信息写入日志,因此如果您有类似复制的内容,这可能会使日志读取器代理发疯,因为它将有太多记录需要处理(有关于解决方法的整个主题,但我我偏离了轨道)。话虽如此 - 这更像是一种特殊情况的删除,可能只应作为最后的手段使用(或者当您需要指定要删除的某些内容时)。
;WITH CTE AS
(
select TOP 1000 * -- Depending on the blocking, you may want to up/down this amount
from mytable
)
delete from CTE;
WHILE (@@ROWCOUNT > 0)
BEGIN
WAITFOR DELAY '00:00:03'; -- Gives times for other queries to process/helps with blocking
;WITH CTE AS
(
select TOP 1000 *
from mytable
)
delete from CTE;
END