假设我有一张10000000记录的表。这两种解决方案有什么区别?
删除数据:
DELETE FROM MyTable
逐行删除带有应用程序的所有数据:
DELETE FROM MyTable WHERE ID = @SelectedID
第一种解决方案是否具有最佳性能? 对日志和性能有什么影响?
答案 0 :(得分:21)
如果您需要限制需要删除的行而不进行完全删除,或者您不能使用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是最好的方法,如果可能的话,我会使用它。但它不能在所有情况下使用。另请注意,TRUNCATE将重置表的IDENTITY值(如果有)。
如果您使用的是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
答案 1 :(得分:14)
如果您的表格中有这么多记录,而您想要全部删除这些记录,则应考虑truncate <table>
而不是delete from <table>
。它会快得多,但要注意它不能激活触发器。
有关详细信息,请参阅(本例sql server 2000): http://msdn.microsoft.com/en-us/library/aa260621%28SQL.80%29.aspx
删除应用程序逐行中的表将在很长一段时间内结束,因为您的dbms无法优化任何事情,因为它事先并不知道您要删除一切。
答案 2 :(得分:3)
第一个明显有更好的表现。
当你指定DELETE [MyTable]时,它只会删除所有内容而不会检查ID。第二个将浪费时间和磁盘操作来每次删除它之前找到相应的记录。
它也变得更糟,因为每次记录从表格中间消失时,引擎可能想要压缩磁盘上的数据,从而浪费时间并再次工作。
也许更好的想法是按降序删除基于聚簇索引列的数据。然后在每次删除操作时,表格基本上都会被截断。
答案 3 :(得分:3)
选项1将创建一个非常大的事务,并对日志/性能产生很大影响,以及升级锁定以使表不可用。 选项2将会更慢,尽管它会对日志产生较小的影响(假设批量/完整模式)
如果你想摆脱所有数据,Truncate Table MyTable将比两者都快,虽然它没有过滤行的工具,它在后面做了元数据更改并且基本上放弃了IAM在地板上有问题的表格。
答案 4 :(得分:2)
清除表格的最佳效果会带来TRUNCATE TABLE MyTable
。有关更详细的解释,请参阅http://msdn.microsoft.com/en-us/library/ms177570.aspx
答案 5 :(得分:0)
第一个会从表格中删除所有数据,并且会有更好的表现,即您的第二个人只会删除来自特定密钥的数据。
现在,如果您必须删除表中的所有数据而不依赖于使用回滚,请考虑使用truncate table
答案 6 :(得分:0)
基本上,它建议:
...
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