Tara Kizer Blog

Tara Kizer

Controlled DELETE

So how do you DELETE thousands/millions of rows from a table without blocking anyone for long periods of time? 

Well, here is an example:

DECLARE @Count INT
DECLARE @Error INT

SELECT @Count = COUNT(*)
FROM SomeTable MLE
WHERE SomeDateColumn < (GETDATE() - 182) -- anything older than 6 months

SET ROWCOUNT 10000

WHILE @Count > 0
BEGIN

BEGIN TRAN

DELETE FROM SomeTable
WHERE SomeDateColumn < (GETDATE() - 182)

SELECT @Error = @@ERROR

IF @@ERROR = 0

COMMIT TRAN

ELSE

ROLLBACK TRAN  

CHECKPOINT

SELECT @Count = COUNT(*)
FROM SomeTable
WHERE SomeDateColumn < (GETDATE() - 182)

END

SET ROWCOUNT 0
SET NOCOUNT OFF

Legacy Comments


DavidM
2003-10-15
re: Controlled DELETE
I usually try to avoid the actual count of table and just use the @@RowCount function.

It this case it would be set at the same time as the Error code.

Select @Error = @@ERROR, @Count = @@ROWCOUNT

Tara
2003-10-15
re: Controlled DELETE
Thanks Graz. We've got several processes that do this, so I'll probably make this modification. The processes are pretty quick as it is, but it wouldn't work to make them better.

Stoad
2003-10-16
re: Controlled DELETE
Very neat!!

robvolk
2003-10-16
re: Controlled DELETE
Graz?

Tara
2003-10-16
re: Controlled DELETE
Damn, my last comment should say: but it wouldn't hurt to make them better.

Satish Balusa
2003-10-17
re: Controlled DELETE
I am glad, I am not alone! I implemented very similar logic, but found 1000 records per loop was the best balance I could strike. I tried this on a variety of tables with various row widths.

Tara
2003-10-20
re: Controlled DELETE
Yeah I'm not sure that the CHECKPOINT is needed either, but it would depend on how big your transaction log can get. We've got plenty of disk space for it to grow, so we could remove it.

joseph
2003-10-20
re: Controlled DELETE
Also I doubt about BEGIN TRANS.I remember nr told me when you USE single delete or update you don't need explicit transaction.
try out this:
declare @rowcount int
select @rowcount=1
SET ROWCOUNT 10000
while @rowcount>0
begin
DELETE FROM SomeTable
WHERE SomeDateColumn < (GETDATE() - 182)

select @rowcount=@@rowcount

end

Ashutosh Nilkanth
2003-10-21
re: Controlled DELETE
You are right joseph. A single SQL statement is executed in an isolated atmoic state and it is processed as a transaction. So even I don't find any relevance of the explicit transaction declaration, unless I'm missing something.

A good tip by Tara.

Tara
2003-10-21
re: Controlled DELETE
The code that I posted is just an example. It doesn't hurt to have the explicit transaction, it just isn't needed.

The code that we actually run in production has more than just one delete.

joseph
2003-10-26
re: Controlled DELETE
Hi Tara
I guess a problem exists:
what do you do if you have something like this?
declare @flag bit
set @flag=0
set rowcount 100
begin tran
delete from a where blah
if @@error <>0 set @flag=1
insert into b(......)
select ..... from x where blah
if @@error <>0 set @flag=1
if @flag=0
commit tran
else rollback tran
I think that works only for Delete and update ,Not insert .Am I right?

Tara
2003-10-28
re: Controlled DELETE
It would work for INSERTs as well. It just processes things a little at a time. So if you were inserting 1000000 rows from another table (maybe from a linked server or something), you could insert say 1000 rows at a time. You would have to delete the 1000 rows from the source server though each loop through though. I'm not sure INSERT is a good example of though of when to do things "controlled" though, but it would work.

crazyjoe
2004-02-23
re: Controlled DELETE
Tara,

This was a great tip...I stumbled acros this usage a while back on SWYNK, and used it with a minor modification, to archive data from a table with nearly 100 million rows on a slow server which housed all of our reporting information. It had to be available during business hours, but the # of iterations it would complete durnig off-hours was unpredictable....so, I modified it by enclosing the entire proc in another loop, using WAITFOR TIME if the current time was during production hours. It took about 3 days to move all the data, but I didn't blow up the server due to transaction log space (in a data warehouse I could just blast all my transactions out of the log as soon as they were committed) and I didn't have to constantly monitor it.

Kristen
2006-09-26
re: Controlled DELETE
Probably overkill, but we record the elasped time for the delete and dynamically adjust the size of the
SET ROWCOUNT @DeleteThisMany
so that if the Server gets busy the delete reduces the effort, and if it finished quickly it adjusts to do more rows per loop. We also put a
WAITFOR DELAY '000:00:05'
at the bottom of the loop to allow other processes to run. Could also force a TLog Backup every N,000,000 rows if needed

Tara
2006-09-26
re: Controlled DELETE
Yes that would be overkill for us.