57

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

从 client_log 中删除

这花了很长时间。

4

15 回答 15

87

查看快得多的截断表。

于 2008-09-15T15:49:16.020 回答
37

我在 msdn transact-SQL 参考中发现了TRUNCATE TABLE 。对于所有感兴趣的人,这里是备注:

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 不能用于参与索引视图的表。

于 2008-09-15T15:50:33.177 回答
17

有一个常见的神话,即 TRUNCATE 以某种方式跳过事务日志。

这是一种误解,在 MSDN 中有明确提及。

这个神话在这里的几个评论中被引用。让我们一起根除它;)

于 2008-09-15T18:02:35.153 回答
6

供参考TRUNCATE TABLE也适用于 MySQL

于 2008-09-15T15:53:36.680 回答
4

我使用以下方法将表格归零,另外还有一个好处是它给我留下了表格的存档副本。

CREATE TABLE `new_table` LIKE `table`;
RENAME TABLE `table` TO `old_table`, `new_table` TO `table`;
于 2008-09-15T19:00:14.297 回答
3

忘记截断和删除。维护您的表定义(以防您想重新创建它)并使用 drop table。

于 2008-09-15T18:57:04.633 回答
1

截断表 client_log

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

于 2008-09-15T15:50:02.633 回答
1

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

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

于 2008-09-15T15:50:21.133 回答
1

truncate table不是独立于 SQL 平台的如果您怀疑您可能会更改数据库提供程序,那么您可能会谨慎使用它。

于 2008-09-15T15:53:52.903 回答
1

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

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

于 2008-09-15T16:28:24.180 回答
0

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

于 2008-09-15T15:49:29.170 回答
0

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

您正在使用外键,对吗?

于 2008-09-15T16:06:16.603 回答
0

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

您应该了解,使用 TRUNCATE 将清除数据,但不会将任何内容记录到事务日志中。写入日志是 DELETE 将永远占用 500 万行的原因。我在开发过程中经常使用 TRUNCATE,但你应该小心在生产数据库上使用它,因为你将无法回滚你的更改。您应该在执行 TRUNCATE 后立即进行完整的数据库备份,以建立新的恢复基础。

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

来自MSDN

DELETE 语句一次删除一个行,并在事务日志中为每个删除的行记录一个条目。TRUNCATE TABLE 通过解除分配用于存储表数据的数据页来移除数据,并且只有页解除分配记录在事务日志中。

我只想说两者之间存在根本区别,因为存在区别,所以会有一些应用程序可能不合适。

于 2008-09-15T17:26:50.777 回答
0

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

  • 删除所有索引;
  • 做通常的删除;
  • 重新创建所有索引。

这可能会加快 DELETE 速度。

于 2008-09-15T18:04:45.477 回答
-1
DELETE * FROM table_name;

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

SELECT DbVendor_SuperFastDeleteAllFunction(tablename, BOZO_BIT) FROM dummy;

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

  • 底层数据库:Oracle, Microsoft, MySQL, PostgreSQL, others, custom...

  • 表格、内容和相关表格:

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

DROP TABLE table_name;

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

于 2008-09-20T18:49:54.350 回答