我必须从包含大约 500 万行的日志表中删除所有行。我最初的尝试是在查询分析器中发出以下命令:

从 client_log 中删除

这花了很长时间。

有帮助吗?

解决方案

查看 截断表 这要快得多。

其他提示

我发现了 截断表 在 msdn transact-SQL 参考中。对于所有感兴趣的人,这里有以下评论:

TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:两者都删除表中的所有行。但 TRUNCATE TABLE 比 DELETE 更快,并且使用更少的系统和事务日志资源。

DELETE 语句一次删除一行,并在事务日志中为每个删除的行记录一个条目。TRUNCATE TABLE 通过释放用于存储表数据的数据页来删除数据,并且仅将页释放记录在事务日志中。

TRUNCATE TABLE 从表中删除所有行,但表结构及其列、约束、索引等保留。新行的标识使用的计数器将重置为该列的种子。如果您想保留身份计数器,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。

不能对由 FOREIGN KEY 约束引用的表使用 TRUNCATE TABLE;相反,请使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 未记录,因此无法激活触发器。

TRUNCATE TABLE 不能用于参与索引视图的表。

有一个常见的误区是 TRUNCATE 会以某种方式跳过事务日志。

这是一个误解,MSDN 里已经明确提到了。

这里的一些评论引用了这个神话。让我们一起消灭它吧;)

以供参考 截断表 也适用于 MySQL

忘记截断和删除。维护您的表定义(如果您想重新创建它)并仅使用删除表。

我使用以下方法将表清零,额外的好处是它为我留下了表的存档副本。

CREATE TABLE `new_table` LIKE `table`;
RENAME TABLE `table` TO `old_table`, `new_table` TO `table`;

truncate table不是 SQL 平台无关。如果你怀疑你 可能 一旦改变数据库提供商,您可能会谨慎使用它。

在 SQL Server 上,您可以使用 Truncate Table 该命令比常规删除更快,并且使用的资源更少。它还会将所有身份字段重置回种子值。

truncate 的缺点是它不能用在由外键引用的表上,并且不会触发任何触发器。此外,如果出现任何问题,您将无法回滚数据。

请注意,TRUNCATE 还将重置任何自动递增键(如果您正在使用这些键)。

如果您不希望丢失自动递增键,可以通过成组删除来加快删除速度(例如,DELETE FROM table WHERE id > 1 AND id < 10000)。它将显着加快速度,并在某些情况下防止数据被锁定。

是的,删除 500 万行可能需要很长时间。我能想到的唯一可能更快的方法是删除表并重新创建它。当然,只有当您想删除表中的所有数据时,这才有效。

截断表client_log

是你最好的选择,截断会杀死表和索引中的所有内容,并重置你拥有的所有种子。

“删除并重新创建表”的建议可能不是一个好的建议,因为这会弄乱您的外键。

您正在使用外键,对吗?

如果由于外键和/或触发器而无法使用 TRUNCATE TABLE,您可以考虑:

  • 删除所有索引;
  • 执行通常的删除操作;
  • 重新创建所有索引。

这可能会加快 DELETE 的速度。

我正在修改我之前的声明:

您应该理解,通过使用截断,数据将被清除,但不会记录到事务日志。写入日志是为什么删除将永远占据500万行的原因。我在开发过程中经常使用截断,但是您应该对在生产数据库上使用它感到谨慎,因为您将无法恢复更改。截断后,您应该立即进行完整的数据库备份,以建立新的恢复基础。

上述声明旨在提示您确保您了解两者之间的差异。不幸的是,它写得不好并且做出了不受支持的陈述,因为我自己实际上没有在两者之间进行任何测试。它是基于我从其他人那里听到的陈述。

微软软件定义网络:

删除语句一次删除一行,并在每个删除行的事务日志中记录一个条目。截断表通过处理用于存储表数据的数据页面来删除数据,并且仅在交易日志中记录了页面交易。

我只是想说,两者之间存在根本区别,并且因为存在区别,所以在某些应用中,其中一种可能不合适。

DELETE * FROM table_name;

过早的优化可能是危险的。优化可能意味着做一些奇怪的事情,但如果它有效,你可能想利用它。

SELECT DbVendor_SuperFastDeleteAllFunction(tablename, BOZO_BIT) FROM dummy;

对于速度,我认为这取决于...

  • 底层数据库:Oracle、Microsoft、MySQL、PostgreSQL、其他、自定义...

  • 该表、其内容和相关表:

可能有删除规则。是否有现有的程序可以删除表中的所有内容?可以针对特定的底层数据库引擎进行优化吗?我们对破坏事物/相关数据有多关心?假设其他相关表不依赖于该表,则执行 DELETE 可能是“最安全”的方法。是否有其他表和查询与此表中的数据相关/依赖于此?如果我们不太关心该表的存在,那么使用 DROP 可能是一种快速方法,这同样取决于底层数据库。

DROP TABLE table_name;

有多少行被删除?是否有其他可以快速收集的信息来优化删除?例如,我们可以判断表是否已经是空的吗?我们能知道是否有数百、数千、数百万、数十亿行吗?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top