SQL 批量删除
Posted
技术标签:
【中文标题】SQL 批量删除【英文标题】:SQL Mass deletes 【发布时间】:2009-10-07 14:15:05 【问题描述】:我正在尝试缩小一些数据库,以便我的开发人员可以将它们加载到他们的本地计算机上。我已经确定了几个包含历史数据(价值 10 年以上)的表,如果我删除超过 X 天的记录,它们将显着减少整体数据库大小(50% 或更多)。
我正在使用的删除语句如下所示,但我的问题是,如何提高此删除语句的速度?数据库已经采用简单的日志记录格式,但日志仍然随着删除语句而增长。有更好的记录方法吗?
这样做会更好吗:
-
将我要保留的数据从当前表复制到临时表中,
截断主表,
将临时数据移回主数据,
收缩日志,
在完成所有需要收缩的表后收缩数据库。
查询示例:
DELETE FROM LoginAttempts WHERE DateAttempt <= GETDATE() - 30
【问题讨论】:
可能重复:***.com/questions/1143096/how-to-delete-faster 我会指出,如果您的开发人员使用的数据库比生产环境小得多,那么您最终将难以让他们编写在他们的机器上可以在可接受的时间范围内工作但超时的代码产品在 dev 中使用小数据集是个坏主意。他们为什么不连接到开发服务器上的数据库。我们不会将大型数据库加载到每个人的个人计算机上! 【参考方案1】:TRUNCATE
和 CREATE AS SELECT
比删除 整个 表要快得多,因为它们生成的重做日志记录更少。
不过,它们是DDL
命令,在某些系统中无法回滚。
但是,如果要删除的行数很少,DELETE
可能仍然更快。
如果要删除一半的行,那么第一个选项很可能会更快,至少在Oracle
中。
【讨论】:
【参考方案2】:您选择移出要保留的数据非常有效,但只有在保留的数据量与被删除的数据相比较小时才有效。
为了更有效地执行删除,您可能希望批处理只删除前 1000 行的删除操作(不要使用 order 子句!),以便每个删除事务的大小保持较小并且不持有锁 /使用很多温度等。
删除所有数据后收缩数据库会使索引碎片化顺便说一句,如果您必须收缩文件组,请将数据移动到另一个文件组并尽可能删除原始文件,任何收缩都会使您碎片化,导致您重新索引并再次使用更多空间(您可以冲洗重复它无济于事)
【讨论】:
【参考方案3】:尽可能使用截断,因为它的方式更快。但是,当有外键引用该表时,这将不起作用。
在大表上执行这些类型的删除语句时,只需将最后 N 天选择到临时表中,删除表,重新创建并插入,会更快。但是,当您有外键时,这可能会变得很棘手。
我在事务日志上的磁盘空间最大化时遇到了问题,所以我有时会使用 while 循环来一次只删除 N 行。
还应确保您的数据库使用简单事务日志,您可能还需要设置自动收缩。
【讨论】:
【参考方案4】:我认为您的想法很成功,将要保留的数据提取到临时表中,截断原始表,然后将其放回。
您还可以使用提取的数据创建一个新表,删除新表并将其重命名为原始表名。这似乎更容易出错,但如果您在维护期间进行此类工作,那么也许没问题。
【讨论】:
以上是关于SQL 批量删除的主要内容,如果未能解决你的问题,请参考以下文章