Batching data chances is encouraged when doing large UPDATE and DELETE statements which affect many rows.
Overview
The idea is that you
Create #full_list and copy the primary ID into this table from prod_table
Define the batch_size, example 1000 and other variables such as the number_of_batches
Loop WHILE @rows_exist = 1
Insert into #temp_batch by selecting TOP(@batch_size)
Perform the UPDATE or DELETE
on prod_table by joining to #temp_batch
DELETE FROM #temp_full_list
Set @rows_exist as infinite loops are frowned upon. Apparently.
Roll Backs
A simple way to roll the data back is to create a new dbo.temp_random_data and insert the at very least the id so you can join back to it. This is really for an UPDATE as DELETE should trigger auditing. You do audit deletes in your database right? :)
BEGIN SET LOCK_TIMEOUT 1000; IF (OBJECT_ID('[dbo].[temp_random_data]') ISNULL) BEGIN PRINT('CREATING temp_random_data') CREATETABLE dbo.temp_random_data ( [id] [int] IDENTITY(1,1) NOTNULL, [insert_date] [datetime] DEFAULT GETDATE(), [id_random_data] [int] NOTNULL, [done] [int] DEFAULT0 ); ALTERTABLE dbo.temp_random_data ADDCONSTRAINT PK_temp_random_data_id PRIMARY KEY(id); END ELSE PRINT 'ALREADY EXISTS temp_random_data' INSERTINTO dbo.temp_random_data (id_random_data, done) SELECT id, 0as done FROM random_data (NOLOCK) WHERE some_bit =1
SET LOCK_TIMEOUT -1 END
DECLARE@batch_sizeINT=1000 DECLARE@rows_to_updateINT= (SELECTCOUNT(1) FROM dbo.temp_random_data WITH (NOLOCK)) DECLARE@number_of_batchesINT= (@rows_to_update/@batch_size) +1 DECLARE@current_batchINT=1 DECLARE@messageVARCHAR(255) DECLARE@rows_existINT=1
DROPTABLE IF EXISTS #temp_batch; CREATETABLE #temp_batch( id_random_data INT );
WHILE @rows_exist=1 BEGIN BEGIN TRY INSERT #temp_batch SELECT TOP (@batch_size) id_random_data FROM dbo.temp_random_data (NOLOCK) WHERE done =0 ORDERBY id_random_data ASC; --- This is the prod table UPDATE random_data WITH (ROWLOCK) SET some_bit =0 FROM random_data AS rd INNERJOIN #temp_batch ON rd.id = #temp_batch.id_random_data; --- This temp_ table can be deleted once done and you are happy with the change UPDATE dbo.temp_random_data SET done =1 FROM dbo.temp_random_data AS trd INNERJOIN #temp_batch ON trd.id_random_data = #temp_batch.id_random_data;
TRUNCATETABLE #temp_batch;
SET@message='Finished batch '+CAST(@current_batchASVARCHAR) +' of '+CAST(@number_of_batchesASVARCHAR) +'. '+CAST(CAST(GETDATE() AS SMALLDATETIME) ASVARCHAR) RAISERROR(@message, 10, 1);
SET@current_batch=@current_batch+1;
END TRY BEGIN CATCH PRINT ERROR_MESSAGE(); BREAK; END CATCH
IF NOTEXISTS (SELECT TOP 11FROM dbo.temp_random_data WHERE done =0) SET@rows_exist=0;