删除大表中的所有数据的最快方法

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

从client_log中删除

花了很长时间。

检查截断表 ,这是快得多。

我在msdn的transact-SQL参考中发现了TRUNCATE TABLE 。 对此感兴趣的是这里的评论:

TRUNCATE TABLE在function上与不带WHERE子句的DELETE语句相同:都删除表中的所有行。 但是TRUNCATE TABLE比DELETE使用更less的系统和事务日志资源。

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

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

您不能在由FOREIGN KEY约束引用的表上使用TRUNCATE TABLE; 而是使用DELETE语句,而不使用WHERE子句。 由于TRUNCATE TABLE未logging,因此无法激活触发器。

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

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

这是误解,在MSDN中明确提到。

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

参考TRUNCATE TABLE也适用于MySQL

忘记截断和删除。 维护你的表定义(如果你想重新创build它),只需使用drop table。

我使用下面的方法来清零表格,还有额外的好处,它将表格的存档副本留给我。

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

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

在SQL Server上,您可以使用比常规删除更快的Truncate Table命令,并且使用的资源也更less。 它会将任何标识字段重置为种子值。

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

请注意,TRUNCATE也将重置所有自动递增键,如果您正在使用这些键。

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

是的,删除500万行可能需要很长时间。 我能想到的唯一可能更快的方法是删除表并重新创build它。 当然,如果你想删除表中的所有数据,这只会起作用。

截断表client_log

是你最好的select,截断杀死表和索引中的所有内容,并重置你得到的种子。

“删除并重新创build表格”的build议可能不是一个好的方法,因为这会导致你的外键失效。

你正在使用外键,对吗?

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

  • 放下所有指标;
  • 做平常的DELETE;
  • 重新创build所有索引。

这可能会稍微加快DELETE。

我正在修改我以前的发言:

你应该明白,通过使用TRUNCATE数据将被清除,但没有什么会被logging到事务日志。 写入日志是为什么DELETE将在500万行上永远占用。 我经常在开发过程中使用TRUNCATE,但是在生产数据库上使用它应该小心,因为您将无法回滚您的更改。 在做完TRUNCATE之后,您应该立即进行完整的数据库备份,以便为恢复build立新的基础。

以上声明旨在促使您确定您明白两者之间存在差异。 不幸的是,它写得不好并且没有支持,因为我没有在两者之间做任何testing。 这是基于我从别人那里听到的陈述。

来自MSDN :

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

我只是想说,两者之间有一个根本的区别,因为这两者之间有区别,所以会出现其中一个可能不合适的应用程序。

 DELETE * FROM table_name; 

不成熟的优化可能是危险的。 优化可能意味着做一些奇怪的事情,但如果它起作用,你可能想利用它。

 SELECT DbVendor_SuperFastDeleteAllFunction(tablename, BOZO_BIT) FROM dummy; 

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

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

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

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

 DROP TABLE table_name; 

有多less行被删除? 是否还有其他信息能够快速收集到优化删除的信息? 例如,我们可以告诉桌子是否已经空了? 我们能否告诉我们是否有数百,数千,数百亿的行?