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

时间:2016-12-14 08:59:25

标签: sql-server performance stored-procedures database-performance

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

要删除行,我创建了一个过程,从原始表中选择每个myID的最大值(这是因为错误是我们在字段值中添加了更多的零,所以最大值是错误的,这个寄存器必须被删除),并在备份表中搜索此寄存器的myID和值,我删除该行。

例如,一行是:

ID myId 其他字段......
2 2345 25948238400 其他值......

程序是:

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天......

如何改善此流程的效果?

2 个答案:

答案 0 :(得分: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 

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

答案 1 :(得分:0)

如果您尝试一次性删除所有服务器,服务器可能会超载并且无法执行其他任务,因此请批量执行此操作,您可以停止并在必要时稍后继续。调整顶部(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