4

我正在尝试缩小一些数据库,以便我的开发人员可以将它们加载到他们的本地机器上。我已经确定了几个包含历史数据(价值 10 年以上)的表,如果我删除超过 X 天的记录,它们将显着减少整体数据库大小(50% 或更多)。

我正在使用的 delete 语句如下所示,但我的问题是,如何提高这个 delete 语句的速度?数据库已经采用简单的日志记录格式,但日志仍然随着删除语句而增长。有更好的记录方法吗?

我这样做会更好吗:

  1. 将我要保留的数据从当前表复制到临时表中,
  2. 截断主表,
  3. 将数据从 temp 移回主节点,
  4. 收缩日志,
  5. 完成所有需要收缩的表后收缩数据库。

查询示例:

DELETE FROM LoginAttempts WHERE DateAttempt <= GETDATE() - 30
4

4 回答 4

2

TRUNCATE并且比删除整个CREATE AS SELECT表要快得多,因为它们生成的重做日志记录更少。

但是,它们是DDL命令,在某些系统中无法回滚。

但是,DELETE如果要删除的行数很少,可能仍然会更快。

如果要删除一半的行,那么第一个选项很可能会更快,至少在Oracle.

于 2009-10-07T14:21:45.470 回答
1

您选择移出要保留的数据是非常有效的,但只有在保留的数据量与被删除的数据相比较小的情况下才有效。

为了更有效地执行删除,您可能希望批处理只删除前 1000 行的删除操作(不要使用 order 子句!),以便每个删除事务的大小保持较小并且不持有锁/使用太多临时等等

删除所有数据后收缩数据库将使索引碎片化顺便说一句,如果您必须收缩文件组,请将数据移动到另一个文件组并尽可能删除原始文件,任何收缩都会使您碎片化,导致您重新索引并使用再次获得更多空间(您可以冲洗重复但无济于事)

于 2009-10-07T14:22:17.713 回答
0

尽可能使用截断,因为它的方式更快。但是,当有引用表的外键时,这将不起作用。

在大表上执行这些类型的删除语句时,只需将最后 N 天选择到临时表中,删除表,重新创建并插入会更快。但是,当您有外键时,这可能会变得很棘手。

我在事务日志上最大化磁盘空间时遇到了问题,所以我有时会使用 while 循环来一次只删除 N 行。

还应确保您的数据库使用简单事务日志,您可能还需要设置自动收缩。

于 2009-10-07T14:26:24.103 回答
0

我认为您很想将要保留的数据提取到临时表中,截断原始表,然后将其放回原处。

您还可以使用提取的数据创建一个新表,删除新表并将其重命名为原始表名。这似乎更容易出错,但是如果您在维护期间进行此类工作,那么也许没问题。

于 2009-10-08T15:18:41.647 回答