删除大表中的所有数据的最快方法
我不得不从包含大约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行被删除? 是否还有其他信息能够快速收集到优化删除的信息? 例如,我们可以告诉桌子是否已经空了? 我们能否告诉我们是否有数百,数千,数百亿的行?