• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
fly_zj
博客园    首页    新随笔    联系   管理    订阅  订阅

小批量的删除大表数据

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

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去做,所以如果时间不是重点,

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

posted @ 2012-08-19 16:34  fly_zj  阅读(579)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3