MSSQL大删除

我有一个MSSQL数据库中的表,其中包含超过100万的logging分布在大约100天的数据。 我需要基于它的date清除这些数据,这是表中的索引字段。 我试过对个别date做DELETE FROM,但执行时间很长,导致服务器性能下降。 有没有更好的方法来删除这么多的logging? 其中一些数据仍然是必需的,所以不幸的是我不能使用截断。

非常感谢尼克

按照以下stream程执行类似任务时,我获得了最好的成功:

  1. 将数据复制到临时表中
  2. 截断原始表以清除所有数据
  3. 将临时表中的所有内容移回到原始表中

这样做的一个主要好处就是在将数据放回到原始表中时,索引将被重build。

那么,如果你正在使用SQL Server分区,那么你可能会根据date列来切换不再需要的分区。 也许考虑未来的实施。

我认为你唯一的select可能是以较小的批次删除数据,而不是一击,以避免任何潜在的阻塞问题。

您可以删除表上的所有索引,从表中删除,然后重新创build索引。 这可能会加快速度,但这取决于未删除logging的百分比。

你可以删除更小的块。 而不是说,一个星期值得尝试只是一天。 如果这太多,一次只需要一个小时。

另一种select是将您想要的数据选入另一个表格。 你可以用这种方式设置分区。

如果date索引是聚簇索引,则删除应该会更快,因为它们都将在磁盘上靠近在一起。

我不喜欢或主张提到的临时表build议。 如果服务器碰巧在删除步骤和插入步骤之间停下来,你会丢失数据。

我会更有可能去与以下之一:

BCP要保留的数据(使用QUERYOUT的BCP),截断,重新导入。 与临时表相同,整体风险较低。

将数据复制到另一个永久表,无论是在同一个数据库或不同的数据库,然后将其拉回。

使用SET ROWCOUNT技术批量删除。 如果你小心翼翼,狡猾,你可以循环这个,所以它发生在循环范围之外,所以删除是独立提交的。 除非您的聚集索引与您如何删除数据相关,否则会导致大量的表碎片。

在某些大容量OLTP数据库中,最好不要删除数据。 开发人员可以创build“IsDeleted”字段或类似的东西。 但这是未来的考虑。

至于你接受的答案。 我不相信,如果你将复制100Mb的数据,它会工作得更快,然后简单的DELETE方法。 这将是非常沉重的负担和大交易日志的增长。 一般来说,这取决于在删除完成后,您希望保留多less数据。

我会推荐的是

1)如果你可以在非激活时间运行你的查询,你应该发出独占表锁,然后删除logging。 这将节省时间SQL服务器将花锁传播到许多单独的行

2)如果第一种方法是不可能的,然后删除块,我会同意约翰Sansom。 当一个非常大的事务阻塞了大量的其他活动用户事务时,问题就开始了……所以你必须在小部分中进行删除,每个事务都在自己的事务中进行…

3)你也可以暂时closures(或删除,然后重新创build)之前/之后删除触发器和约束(包括外键),但是存在完整性风险,这种方法需要一些实验。

AFAIK,禁用/启用索引不会改善这种情况,因为当你删除logging时,索引树中会出现“漏洞”…所以这可能会影响下一个SQL查询对同一个表的性能,并且迟早可能要重build索引,但我从来没有看到任何影响如何索引(即使你有太多的索引)可能会降低删除操作的速度

在大多数情况下,当DELETE查询(您可能检查查询计划)或者您有太多外键或重触发逻辑时,DELETE的性能不佳。

大块删除。

根据您的条件select一个删除,但select有一个TOP 100000 – 所以只有100000行被删除每个电话。 呼叫,直到没有更多被删除。