小批量的删除大表数据

当要删除大表的数据时,一定要小批量的删除相应行,这样带来的好处为:

1:一个事物删除少数行,避免由行锁转化为表锁,从而阻塞业务的正常运行

2:事务提交后,日志文件可以重复使用!

 

以下有两种小批量的删除行的解决方案,测试它们的性能如何:

 

首先填充测试表:

USE AdventureWorks

GO



SELECT * INTO TransactionHistory_temp FROM Production.TransactionHistory(nolock)

SELECT * INTO TransactionHistory_top FROM Production.TransactionHistory(nolock)



SELECT * FROM TransactionHistory_temp WHERE modifiedDate<'2004-04-02 00:00:00.000'

SELECT * FROM TransactionHistory_top WHERE modifiedDate<'2004-04-02 00:00:00.000'

--create index

CREATE CLUSTERED INDEX ix_TransactionID ON TransactionHistory_temp(TransactionID)

CREATE CLUSTERED INDEX ix_TransactionID ON TransactionHistory_top(TransactionID)

 

第一种解决方法使用top的方式来删除行

DBCC FREEPROCCACHE

CHECKPOINT

DBCC DROPCLEANBUFFERS



DECLARE @start_top datetime=getdate();



while(1=1)

BEGIN

    DELETE top(100) FROM TransactionHistory_top 

    WHERE modifiedDate<'2004-04-02 00:00:00.000'

    

    if(@@rowcount<>100)

    BEGIN

        SELECT datediff(SECOND,@start_top,getdate()) AS "使用[top]花费的时间"

        return;

    end

END

时间为:【单位秒】

image

 

 

第二种解决方案使用临时表来删除行:

DBCC FREEPROCCACHE

CHECKPOINT

DBCC DROPCLEANBUFFERS



DECLARE @start_temp datetime=getdate();



CREATE table #transaction (transactionid INT PRIMARY KEY)

INSERT INTO #transaction SELECT transactionid FROM TransactionHistory_temp(nolock)

                         WHERE  modifiedDate<'2004-04-02 00:00:00.000'



declare @temp table(transactionid INT )



WHILE exists(SELECT TOP 1 1 FROM #transaction) 

BEGIN

    DELETE FROM @temp;

    INSERT INTO @temp SELECT TOP 100 transactionid FROM #transaction



    DELETE FROM TransactionHistory_temp WHERE transactionid IN 

                                                            ( 

                                                                SELECT transactionid

                                                                FROM @temp

                                                            )  

    DELETE FROM #transaction WHERE transactionid IN 

                                                (

                                                    SELECT transactionid 

                                                    FROM @temp

                                                )

                      

END



SELECT datediff(second ,@start_temp,getdate()) AS "使用[temp]花费的时间"
 
 

时间为:【单位秒】

image

 

 

可以看到使用临时表速度快了5倍有余,但是需要手写的代码就多了点,第一种解决方案代码清晰明了,通常删除大表数据都是在凌晨以后通过创建JOB去做,所以如果时间不是重点,

我倾向使用第一种解决方案,如果删除的速度很重要,可以选择第二种解决方案!

你可能感兴趣的:(删除)