【问题标题】:How to delete a lot of records from SQL database fast?如何快速从 SQL 数据库中删除大量记录?
【发布时间】:2013-06-29 16:37:54
【问题描述】:

我们有一个包含大约 150 万条记录的表。这个表有很多来自不同表的外键关系。

问题是 100 万条记录只是重复的,必须删除。我们当时尝试删除 1000 条记录,但这是一个非常缓慢的过程。

我的想法是将必须保留的临时记录复制到新表中。 截断现有的并复制必须保留的记录。恢复主键和与其他表的所有关系。所以从客户端你看不出有什么区别。

不确定这是否是一种有效的方法。

如果是的话,我很想看到它的基本实现,这样我就可以遵循并申请我的案例。 如果没有,我希望看到有效的方法。

谢谢

【问题讨论】:

  • 这是一次性清理,还是您的系统养成了复制数据的习惯?
  • 您在列上是否有一个索引来过滤掉要删除的行?
  • 禁用索引,然后将唯一数据500K复制到表B中,然后截断并删除原始表,然后将B重命名为原始名称,然后进行索引
  • @German,就像索引一样,也添加关系,或者如果关系太多和复杂,禁用索引,将重复数据移动到表 B 然后重新创建索引(不启用它),我认为,索引是您将过程视为蜗牛移动的原因
  • 您不能截断带有 FK 的表。

标签: sql sql-server sql-server-2008


【解决方案1】:

我们公司有一堆临时数据存储在数据库中。当我们需要删除一堆时,我们将其分成几百行并一次删除它们。我们有一个应用程序,它的唯一目的就是一遍又一遍地运行一些这样的查询:

with topFew as (select top 100 * from table) delete topFew

我建议你做一个像这样简单的东西,让它运行几个小时。在处理过程中去做其他事情。

【讨论】:

  • 是的,很好,可以由第三人完成。党的应用程序,将每个删除操作作为低优先级事务发送到数据库,我试图投票,但系统告诉今天足够了:D
【解决方案2】:

删除的性能可以通过使用 rowid 自连接表来提高。它甚至可以通过使用批量收集和 FORALL 进行优化

     DECLARE

     limit_in integer;
     CURSOR C1 is
     Select min(b.rowid) 
       from table_name a, table_name b
      where a.primary_key = b.primary_key;

      TYPE C1_rec IS TABLE OF C1%ROWTYPE
      INDEX BY PLS_INTEGER;

     C1_record C1_rec

     BEGIN
     limit_in:=10000  --- Can be changed based on performance
     OPEN C1;
       LOOP
        FETCH C1 BULK COLLECT INTO C1_record LIMIT limit_in;
        FORALL indx in 1..c1_record.count
         DELETE FROM table_name where row_id = C1_record(i);
         commit;
       END LOOP;
     END;

要删除的表有子表,所以会有约束违规。

所以在执行上述代码之前,最好将外键约束更改为 HAVE DELETE CASCADE。我们不能修改约束来添加删除级联。所以外键应该被删除并重新创建以删除级联

    ALTER child_table
    ADD CONSTRAINT fk_name
    foreign_key (C1)
    references parent_table (C2) on delete cascade;

删除级联也会清理您的子表..

【讨论】:

  • 这是一个 Oracle 解决方案,OP 已经用 SQL Server 标记了他的问题
  • SQL server 也可以使用同样的概念。
  • 我不知道它是否容易翻译,我不知道 SQL Server 中 rowid 和 bulk collect 的任何现成等效项
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多