【问题标题】:Delete large amount of data on SQL server删除 SQL Server 上的大量数据
【发布时间】:2019-12-05 12:56:04
【问题描述】:

我需要在 SQL Server 中删除 900,000.00 万条记录。

我想知道最好的方法。

我做了以下 SELECT。

DeleteTable: 
   DELETE TOP(1000)  TAB1 
   FROM TABLE1 TAB1 
     LEFT JOIN TABLE2 TAB2 ON TAB1.ID_PRODUCT = AB2.ID_PRODUCT 
   WHERE TAB2.ID_PRODUCT IS NULL; 
   IF @@ROWCOUNT <> 0 goto DeleteTable; 

我想知道是否可以优化此查询以获得更好的删除性能

谢谢。

【问题讨论】:

  • 如果EXISTS 条件比外连接更快,我不会感到惊讶
  • 900,000.00 million?!?那是多少?
  • @jarlh 我猜 OP 意味着 900 万......
  • 为什么不直接使用truncate
  • 任何依赖,如 fk 引用等?

标签: sql-server tsql sql-delete


【解决方案1】:

删除 900,000,000 行需要很长时间,而且您可能会用完临时存储空间 - 除非您有大量存储空间。您在一种方法中以增量方式删除行的方法。

如果您的日志记录未设置为“简单”,那么您可能需要考虑这一点。使用您的增量删除方法,这至少可以防止日志被填满。

对于您的查询,您希望tab2(id_product) 有一个索引。我不确定tab1(id_product) 上的索引是否真的有帮助。

另外一个就是重新建表,因为inserts和建表效率更高。

为此,您基本上可以这样做:

select t1.*
into temp_tab1
from tab1 t1 
where exists (select 1 from table2 t2 where t2.id_product = t1.id_product);

truncate table tab1;  -- back it up first!

insert into tab1
    select *
    from temp_tab1;

注意:如果您有一个标识列,您可能需要设置标识插入。此外,如果您有此表的外键约束,那么您需要格外小心。

最后,如果这是您需要反复做的事情,那么您应该考虑对表进行分区。删除分区比删除行更有效。

【讨论】:

  • 如果它是一个实时数据库,您可能还希望将整个事物包装在具有SERIALIZABLE 隔离级别的事务中。
【解决方案2】:

如果数据库是高度事务性的并且表有大量的读写活动,您需要小心,这主要是因为您可能在删除过程中阻塞了其他会话。一种较慢但影响较小的方法是使用游标删除记录。这样做的方法是将 product_id 放入 #table 并使用 product_id 作为谓词从实际表中删除。

【讨论】:

  • 感谢您的回答。这个基地没有高交易。所以我可以使用类似于我上面的代码的东西,我只是不知道如何以最具性能的方式使用它,使用 JOIN、EXISTS 或其他方式会更好吗?
猜你喜欢
  • 2011-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-14
  • 1970-01-01
相关资源
最近更新 更多