Sql server 删除sql server中的大量数据
假设我有一个有10000000条记录的表。这两种解决方案的区别是什么Sql server 删除sql server中的大量数据,sql-server,performance,sql-delete,Sql Server,Performance,Sql Delete,假设我有一个有10000000条记录的表。这两种解决方案的区别是什么 删除以下数据: DELETE FROM MyTable 逐行删除应用程序中的所有数据: DELETE FROM MyTable WHERE ID = @SelectedID 第一个解决方案是否具有最佳性能? 对日志和性能有什么影响?第一个显然具有更好的性能 当您指定DELETE[MyTable]时,它将简单地擦除所有内容,而不检查ID。第二个选项将浪费时间和磁盘操作,以便在每次删除记录之前找到相应的记录 更糟糕的是,每
DELETE FROM MyTable
DELETE FROM MyTable WHERE ID = @SelectedID
对日志和性能有什么影响?第一个显然具有更好的性能 当您指定DELETE[MyTable]时,它将简单地擦除所有内容,而不检查ID。第二个选项将浪费时间和磁盘操作,以便在每次删除记录之前找到相应的记录 更糟糕的是,每次记录从表的中间消失时,引擎可能希望压缩磁盘上的数据,从而浪费时间并再次工作
也许更好的办法是根据聚集索引列按降序删除数据。然后,在每次删除操作中,表基本上都会从末尾被截断。选项1将创建一个非常大的事务,并对日志/性能产生很大影响,同时会升级锁,使表不可用。 选项2速度较慢,但对日志的影响较小(假设为批量/完整模式)
如果您想清除所有数据,Truncate Table MyTable将比两者都快,尽管它没有过滤行的功能,但它会在后面更改元数据,基本上会将问题表的IAM放在地板上。清除表的最佳性能是
Truncate Table MyTable
。请参阅更详细的解释< /p> 如果您的表中有许多记录,并且希望删除所有记录,则应考虑<代码>截断< /代码>,而不是<代码>从删除。它会快得多,但请注意它无法激活触发器
有关更多详细信息,请参见(本例为sql server 2000):
逐行删除应用程序中的表将花费很长时间,因为dbms无法优化任何内容,因为它事先不知道,您将删除所有内容。第一个将从表中删除所有数据,并且与第二个仅从特定键中删除数据的用户相比性能更好
现在,如果您必须从表中删除所有数据,并且不依赖于使用回滚,请考虑使用a,如果您需要限制需要删除的行而不执行完全删除,或者您不能使用TRUNCATE table(例如,该表由FK约束引用,或包含在索引视图中),然后您可以分块执行删除操作:
DECLARE @RowsDeleted INTEGER
SET @RowsDeleted = 1
WHILE (@RowsDeleted > 0)
BEGIN
-- delete 10,000 rows a time
DELETE TOP (10000) FROM MyTable [WHERE .....] -- WHERE is optional
SET @RowsDeleted = @@ROWCOUNT
END
一般来说,截断是最好的方法,如果可能的话,我会使用它。但它不能用于所有场景。另外,请注意TRUNCATE将重置表的标识值(如果有)
如果您使用的是SQL 2000或更早版本,则TOP条件不可用,因此可以改用SET ROWCOUNT
DECLARE @RowsDeleted INTEGER
SET @RowsDeleted = 1
SET ROWCOUNT 10000 -- delete 10,000 rows a time
WHILE (@RowsDeleted > 0)
BEGIN
DELETE FROM MyTable [WHERE .....] -- WHERE is optional
SET @RowsDeleted = @@ROWCOUNT
END
找到这个
基本上,它建议:
如果仍在执行截断的事务范围内,则可以回滚截断,这与人们普遍认为的事务化相反-在提交之前不会删除已解除分配的IAM,因此可以通过恢复IAM回滚该IAM。只需读取它,您是对的,在sql server中可以回滚截断。我认为oracle不可能(根据文档),我不能使用TRUNCATE,因为MyTable有外键,我还需要筛选数据的where子句如果需要where子句,就不能使用TRUNCATE。我猜我们误解了你的问题,如果你不想删除表中的所有数据,请参阅Andrew的第一部分,了解选项一和选项二之间的区别。我不能使用TRUNCATE,因为MyTable有外键。我还需要WHERE子句来过滤数据你说:“也许更好的办法是根据聚集索引列按降序删除数据。然后,在每次删除操作中,表基本上从末尾被截断。“您能详细描述一下吗?数据库引擎以群集磁盘顺序在磁盘上物理分配数据。如果要删除具有最高索引值的记录,这将基本上导致切断文件尾部,而不必在文件中间删除某些可能发生的数据。当您添加记录以尝试将其附加到文件末尾时,这一点尤其重要。我可以想象,从末尾删除记录也会提高性能。您可能不想使用SET ROWCOUNT来支持SELECT/INSERT/UPDATE/DELETE TOP(N)。。。原因是什么?看看这里:这里:好的观点(假设SQL 2005或更高版本),这可能是一个安全的赌注。更新了my Answer如果要实际运行它,请将回滚事务替换为提交事务。您还需要删除中间表,否则下一次执行此查询将失败。当目标表存在时,SELECT INTO失败。因此,在提交事务之前只需添加以下内容:
DROP TABLE dbo.bigtable\u intermediate代码>我认为您还需要临时将恢复模式设置为“大容量日志”<代码>更改数据库YourDbName设置恢复批量记录;转到
。有关详细信息,请查看此链接:
BEGIN TRANSACTION
SELECT *
INTO dbo.bigtable_intermediate
FROM dbo.bigtable
WHERE Id % 2 = 0;
TRUNCATE TABLE dbo.bigtable;
SET IDENTITY_INSERT dbo.bigTable ON;
INSERT INTO dbo.bigtable WITH (TABLOCK) (Id, c1, c2, c3)
SELECT Id, c1, c2, c3 FROM dbo.bigtable_intermediate ORDER BY Id;
SET IDENTITY_INSERT dbo.bigtable OFF;
ROLLBACK TRANSACTION