删除所有(1200万)记录后,SQL Server“空表”运行缓慢吗?


27

我有一个大约有150列的SQL Server 2008实例。我以前在该表中填充了大约1200万个条目,但是此后清除了该表以准备新的数据集。

然而,命令,一旦在空表上立即跑如count(*)select top 1000SQL Management Studio现在采取亿万运行。

SELECT COUNT(*) FROM TABLE_NAME 

花了11分钟以上的时间来返回0,SELECT TOP 1000花了将近10分钟的时间来返回一个空表。

我还注意到硬盘上的可用空间实际上已经消失了(从大约100G减少到20G)。之间发生的唯一事情是我运行了一个查询:

DELETE FROM TABLE_NAME

到底是怎么回事?!?


5
您的数据库使用什么恢复模型?如果它是“ Full”,则您的SQL实例将存储所有这些删除的记录,这可能是您的可用空间所经过的地方。如果需要完全恢复,我建议使用TRUNCATE TABLE代替DELETE FROM
Tullo_x86'3

2
150列?该表可能已满-大多数元组应该小得多。但是,如果没有完整的上下文,则无法说。
Clockwork-Muse 2012年

Answers:


42

您已经被告知为什么TRUNCATE会比更快,更好/更性感DELETE,但是仍然有一个问题需要解决:

为什么完成SELECT后变慢?DELETE

这是因为DELETE幻像行。该表与有1200万行时一样大,即使没有。要计算行数(0),需要花费与计算1200万行相同的时间。随着时间的推移,虚影清理过程将垃圾收集这些幻影记录并释放包含幻影的页面,您的SELECT将会加速。但是,现在,如果您签Skipped Ghosted Records/sec入perfmon,可能会在期间暴涨SELECT COUNT(*)。您还可以通过重建表来加快处理速度:ALTER TABLE ... REBUILD

TRUNCATE 也会解决这个问题,因为它不会留下任何阴影。

另请参阅《存储引擎内部:深度清除Ghost》


13

DELETE语句一次删除一个表中的行,记录中的每一行transaction log以及维护log sequence number (LSN)信息。由于您提到表中有大量数据(1200万条记录),因此在删除硬盘空间不足后,请检查数据库日志文件的大小。它很可能会增长。

更好的方法是:

TRUNCATE TABLE_NAME

2
+1,与Oracle DB完全相同。如果使用导致记录记录的语句,它将随着时间的推移降低数据库的速度。
Petro Semeniuk 2012年

@PetroSemeniuk根据我在Oracle上的回忆,删除仅留下高水位线,截断将重置高水位线。我相信任何需要全面扫描的操作都会扫描这些块,直到达到高水位线为止。因此,删除可能有助于索引操作,但不能扫描。TRUNCATE是正确的操作。
格伦2012年

3

(这最初是对@DaveE答案的评论,但由于时间太长,我将其放入自己的答案中)

TRUNCATE 已记录的操作。否则必须与ACID不兼容。但是,TRUNCATE和之间的区别DELETE

  • 日志空间使用情况:TRUNCATE仅记录已释放的页面/范围*,而DELETE记录单个行。
  • 锁用法:TRUNCATE通常使用较少的锁,因为它需要表锁和页锁,而不是DELETE使用行锁**。
  • IDENTITYsequence:TRUNCATE重置表上的标识序列(如果存在)。

(*一个区= 8页。TRUNCATE如果它们全部来自一个表,则将记录/删除区,否则,它将从混合区中记录/删除页。

**这样做的副作用是,有DELETE FROM TABLE可能使空页分配给表,具体取决于操作是否可以获取独占表锁。)

因此(回到原始问题)TRUNCATE TABLEDELETE FROM TABLE在清空表但要保留结构时要好得多(注意:TRUNCATE不能在被另一个表的外键引用的表上使用)。

如@Tullo的评论中所述,还要检查数据库的恢复模型-如果数据库已满,则您需要开始执行日志备份,或者将恢复模型更改为简单。完成上述任何一项操作后,您可能希望将日志文件缩小为一次性操作(注意:日志文件),以便回收所有可用空间。

最后,要注意的另一件事-表统计信息。运行UPDATE STATISTICS <TABLENAME>' afterTRUNCATE /DELETE`,以便查询优化程序不会被旧的统计信息绊倒。


2

(注意:我不是DBA)DELETE是一个记录的操作,它不会释放所使用的空间。您可能有一个大的事务日志,占用空间,并且在“空”表空间上运行表扫描。我猜您需要清除事务日志并缩小数据库。 这篇StackOverflow文章应该使您入门。

并在将来需要时使用TRUNCATE TABLE。

编辑:我关于未记录TRUNCATE的语句是错误的。删除。

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.