在 sql 服务器中删除数百万个寄存器的最快方法

Fastest way to delete millions of registers in sql server

我在 SQL 服务器中有一个很大的 table,其中包含 136.651.894 行。一个月前插入了 7.668.309 个新行,其中一个字段有错误。在插入的那一刻,我创建了一个副本 table 以确保不会发生这种情况,但没有人看到错误,我在加载过程一周后删除了 table。

为了删除行,我创建了一个过程,其中 select 每个 myID 的最大值来自原始 table(这是因为错误是我们在字段值中添加了更多的零,所以最大值错误,必须删除该寄存器),在备份中 table 我在该寄存器中搜索 myID 和值,然后删除该行。

例如一行是:

ID myId 其他字段...
2234525948238400其他值...

程序是:

CREATE PROCEDURE [dbo].[P_DELETE_ROWS] 
AS BEGIN
    DECLARE @myId VARCHAR(22)
    DECLARE @value VARCHAR(20)

  DECLARE c_max CURSOR 
  FOR
    SELECT myId,max ([value]) as maxValue
    FROM t1Original
    group by  myId
    order by maxValuedesc

  OPEN c_max
    FETCH NEXT FROM c_max
    INTO @myId ,@value

  WHILE @@FETCH_STATUS = 0  
    BEGIN
        print 'Deleting '+@myId+' y caudal '+@value +''
        DELETE FROM [t1OriginalCopy] WHERE myId=@myIdAND value=@value
        FETCH NEXT FROM c_max 
        INTO @myId,@value
    END

  CLOSE c_maxs
  DEALLOCATE c_max
END

这个问题是太费时间了,现在执行1天多了...

我怎样才能提高这个进程的性能?

使用 DENSE_RANK 而不是 CURSOR

试试这个

;WITH cte
     AS (SELECT Dense_rank()OVER(partition BY myId ORDER BY value DESC) rn,*
         FROM   [t1OriginalCopy])
DELETE FROM cte
WHERE  rn = 1 

如果 table(t1OriginalCopy) 将在其他一些操作中并行使用,那么您可能必须将删除拆分为多个批次以避免锁定

如果您尝试一次删除所有内容,服务器可能会超载并且无法执行其他任务,因此请分批执行,您可以在必要时停止并稍后继续。调整 'top(100)' 以更改批量大小,具体取决于服务器的管理方式。

Declare @rcount int=1 Select MyID, max([Value]) as maxvalue into #temp from t1Origina group by myID while @rcount>0 begin Delete top (100) o FROM t1Origina o inner join #temp t on o.myId = t.myId and o.value = t.maxvalue set @rcount=@@rowcount END Drop #temp