我不得不从包含大约 500 万行的日志表中删除所有行。我最初的尝试是在查询分析器中发出以下命令:
从 client_log 中删除
这花了很长时间。
查看快得多的截断表。
我在 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 不能用于参与索引视图的表。
有一个常见的神话,即 TRUNCATE 以某种方式跳过事务日志。
这是一种误解,在 MSDN 中有明确提及。
这个神话在这里的几个评论中被引用。让我们一起根除它;)
供参考TRUNCATE TABLE也适用于 MySQL
我使用以下方法将表格归零,另外还有一个好处是它给我留下了表格的存档副本。
CREATE TABLE `new_table` LIKE `table`;
RENAME TABLE `table` TO `old_table`, `new_table` TO `table`;
忘记截断和删除。维护您的表定义(以防您想重新创建它)并使用 drop table。
截断表 client_log
是您最好的选择,截断会杀死表和索引中的所有内容并重置您拥有的任何种子。
在 SQL Server 上,您可以使用Truncate Table
比常规删除更快且使用更少资源的命令。它还将任何身份字段重置回种子值。
truncate 的缺点是它不能用于由外键引用的表,并且不会触发任何触发器。此外,如果出现任何问题,您将无法回滚数据。
truncate table
不是独立于 SQL 平台的。如果您怀疑您可能会更改数据库提供程序,那么您可能会谨慎使用它。
请注意,TRUNCATE 还将重置任何自动递增键,如果您正在使用这些键。
如果您不希望丢失您的自动递增键,您可以通过删除集合来加快删除速度(例如,DELETE FROM table WHERE id > 1 AND id < 10000)。它将显着加快速度,并在某些情况下防止数据被锁定。
是的,好吧,删除 500 万行可能需要很长时间。我能想到的唯一可能更快的方法是删除表并重新创建它。当然,这只有在您想删除表中的所有数据时才有效。
“删除并重新创建表”的建议可能不是一个好建议,因为这会弄乱你的外键。
您正在使用外键,对吗?
我正在修改我之前的声明:
您应该了解,使用 TRUNCATE 将清除数据,但不会将任何内容记录到事务日志中。写入日志是 DELETE 将永远占用 500 万行的原因。我在开发过程中经常使用 TRUNCATE,但你应该小心在生产数据库上使用它,因为你将无法回滚你的更改。您应该在执行 TRUNCATE 后立即进行完整的数据库备份,以建立新的恢复基础。
上述声明旨在提示您确保您了解两者之间的差异。不幸的是,它写得不好并且发表了不受支持的陈述,因为我实际上并没有在两者之间进行任何测试。它基于我从其他人那里听到的陈述。
来自MSDN:
DELETE 语句一次删除一个行,并在事务日志中为每个删除的行记录一个条目。TRUNCATE TABLE 通过解除分配用于存储表数据的数据页来移除数据,并且只有页解除分配记录在事务日志中。
我只想说两者之间存在根本区别,因为存在区别,所以会有一些应用程序可能不合适。
如果由于外键和/或触发器而无法使用 TRUNCATE TABLE,您可以考虑:
这可能会加快 DELETE 速度。
DELETE * FROM table_name;
过早的优化可能是危险的。优化可能意味着做一些奇怪的事情,但如果它有效,你可能想利用它。
SELECT DbVendor_SuperFastDeleteAllFunction(tablename, BOZO_BIT) FROM dummy;
对于速度,我认为这取决于...
底层数据库:Oracle, Microsoft, MySQL, PostgreSQL, others, custom...
表格、内容和相关表格:
可能有删除规则。是否有删除表中所有内容的现有程序?这可以针对特定的底层数据库引擎进行优化吗?我们有多在乎破坏事物/相关数据?假设其他相关表不依赖于该表,执行 DELETE 可能是“最安全”的方式。是否有其他表和查询相关/依赖于该表中的数据?如果我们不太关心这个表是否存在,使用 DROP 可能是一种快速的方法,同样取决于底层数据库。
DROP TABLE table_name;
有多少行被删除?是否有其他可以快速收集的信息来优化删除?例如,我们能否判断该表是否已经为空?我们能分辨出是否有数百、数千、数百万、数十亿行吗?