删除数百万行禁用索引

Rac*_*SQL 5 sql-server sql-server-2014

我有一个包含数百万行的表。我正在删除where year(data) in (2013,2014,2015)。需要4个多小时。我现在试图只删除 2013 年,但它仍然非常非常慢(每年都有超过 600.000 行,并且有一varbinary列用于存储 .PDF 文件)。

我知道索引会降低删除的性能。该Disable表中的两个索引都将是一个好主意,然后重新启用它们?

在此处输入图片说明

如果我创建一个视图并从视图中删除它会更快吗?


编辑:

我做了这个查询以通过前 1 删除它:

delete top (1) from MyTable where year(data) in ( 2013)--,2014,2015)
while @@rowcount > 0
    begin
    delete top (1) from MyTable where year(data) in ( 2013)--,2014,2015)
    end
Run Code Online (Sandbox Code Playgroud)

RDF*_*ozz 5

根据该表与数据库中其他表的互连方式,并假设该表仅包含 2013 年至今的数据,最快的解决方案可能是:

  1. 编写原始表的脚本,并创建一个具有相同结构的新空表。
  2. INSERT将2016年和2017年的数据放入新表中。
  3. DROP原来的表。
  4. 将新表重命名为原始表的名称(请参阅 文​​档ALTER TABLE)。

删除通常比插入慢得多,因此复制表中 25-30% 的记录可能比删除其中 70-75% 的记录要快。但是,当然,您需要有足够的磁盘空间来保存要保留的数据的重复项,以便能够使用此解决方案(如 Toby 在评论中指出的那样)。

如果这样做,您将需要绝对确定新表最终与原始表完全相同,包括任何索引、触发器等。您可能需要截断原始表,重命名它,并将其保留一段时间而不是删除它,只是为了确保您没有遗漏任何内容。此外,在任何聚集索引之外,您可能需要在插入 2016 年和 2017 年数据后添加聚集索引和触发器。如果涉及触发器,请确保您所做的任何操作都会使其余数据保持有效状态。

如果其他表在外键关系中引用您的表(如 Joe Obbish 在评论中建议的那样),那么这会变得更加复杂。我建议编写指向该表的所有外键的脚本,删除它们,然后在新表重命名后重新创建它们。请参阅Aaron Bertrand 撰写的文章的链接以获取有关此问题的帮助。


RMa*_*his 1

我强烈建议您现在对表进行分区。

我将创建一个按年份分区的新表,看起来就像您当前的表一样,然后插入其中。展望未来,您可以更轻松地修剪您的表。

这里有几个很好的分区讨论的链接... http://www.databasejournal.com/features/mssql/partitioning-in-sql-server-part-1.html https://www.datavail.com/blog /四件事-记住-规划-sql-分区/

我不是 SQL Server 人员 - 我看到 MS SQL Server 2016 文档表明 2014 年功能存在一些差异 - 但我找不到 2014 年文档。

这是 MS SQL Server 2008 的链接... https://msdn.microsoft.com/en-us/library/ms188706(v=sql.105).aspx

祝你好运!