Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 删除sql server中的大量数据_Sql Server_Performance_Sql Delete - Fatal编程技术网

Sql server 删除sql server中的大量数据

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。第二个选项将浪费时间和磁盘操作,以便在每次删除记录之前找到相应的记录 更糟糕的是,每

假设我有一个有10000000条记录的表。这两种解决方案的区别是什么

  • 删除以下数据:

    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
    
    找到这个

    基本上,它建议:

  • 通过使用SELECT INTO,将要保留的数据复制到中间表中
  • 截断源表
  • 用INSERT将数据从中间表复制回源表


    如果仍在执行截断的事务范围内,则可以回滚截断,这与人们普遍认为的事务化相反-在提交之前不会删除已解除分配的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