Author |
Topic |
kamii47
Constraint Violating Yak Guru
353 Posts |
Posted - 2012-03-08 : 08:42:25
|
I have a set of tables in which I have to do deletion in a transactionMy problem is that some tables have possibly million records so I have put chunking logic to deletePlease suggest I can do any improvement in the following logicdeclare @tvpJobKeys as tvpJobKeysdeclare @tvpProblamaticJobs as tvpJobKeysSET NOCOUNT ONinsert into @tvpJobKeysSelect IDFrom MyMainTablewhere imjIsDeleted = 1order by CAST(PQTRecordCount AS int) descdeclare @NumberRecords intdeclare @RowCount as intSet @RowCount = 0select @NumberRecords = count(*)from @tvpJobKeysprint 'Total Number of soft deleted Job ' + Cast(@NumberRecords as varchar(max))declare @ID as varchar(8)declare @chunksize as intSet @chunksize = 5000WHILE @RowCount <> @NumberRecords begin BEGIN TRY BEGIN TRANSACTION select @ID = ID From (Select top 1 ID From @tvpJobKeys) as tblJob Update MyMainTable Set imjIsThisAReplicaJob = 0, imjReplicaJobCreateDuration = Null, imjReplicaJobCreatedDate = NULL, imjReplicaParentID = Null, imjIsUpgraded = 0 Where imjReplicaParentID = @ID print 'Job ' + @ID + 'Update MyMainTable ' WHILE ( Exists(Select top 1 * From PieceDetailRecord where fkID = @ID) ) BEGIN DELETE TOP (@chunksize) -- reduce if log still growing From PieceDetailRecord where fkID = @ID END print 'Job ' + @ID + ' Delete PieceDetailRecord' WHILE ( Exists(Select top 1 * From PieceBarcodeRecord where fkID = @ID) ) BEGIN Delete top (@chunksize) From PieceBarcodeRecord where fkID = @ID End print 'Job ' + @ID + ' Delete PieceBarcodeRecord' WHILE ( Exists(Select top 1 * From PackageQuantityRecord where fkID = @ID) ) BEGIN Delete top (@chunksize) From PackageQuantityRecord where fkID = @ID End print 'Job ' + @ID + ' Delete PackageQuantityRecord' Delete From PostageAdjustmentRecord where fkID = @ID print 'Job ' + @ID + ' Delete PostageAdjustmentRecord' Delete From OriginalContainerIdentificationRecord where fkID = @ID print 'Job ' + @ID + ' Delete OriginalContainerIdentificationRecord' Delete From MailPieceUnitRelationShipRecord where fkID = @ID print 'Job ' + @ID + ' Delete MailPieceUnitRelationShipRecord' WHILE ( Exists(Select top 1 * From IntelligentMailRangeRecord where fkID = @ID) ) BEGIN Delete top (@chunksize) From IntelligentMailRangeRecord where fkID = @ID End print 'Job ' + @ID + ' Delete IntelligentMailRangeRecord' WHILE ( Exists(Select top 1 * From ContainerQuantityRecord where fkID = @ID) ) BEGIN Delete top (@chunksize) From ContainerQuantityRecord where fkID = @ID End ..... WHILE ( Exists(Select top 1 * From MyMainTableError where fkID = @ID) ) BEGIN Delete top (@chunksize) From MyMainTableError where fkID = @ID End print 'Job ' + @ID + ' Delete MyMainTableError' Delete From MyMainTable where ID = @ID print 'Job ' + @ID + ' Delete MyMainTable' print 'Job ' + @ID + ' ' + Cast(@RowCount as varchar(max)) delete from @tvpJobKeys where ID = @ID print Cast(Getdate() as varchar(max)) + ' Job Deletion completed' print '------------------------------------------------------------------------------------' COMMIT TRANSACTION SET @RowCount = @RowCount + 1 END TRY BEGIN CATCH delete from @tvpJobKeys where ID = @ID insert into @tvpProblamaticJobs Select @ID END CATCH ENDprint Cast(Getdate() as varchar(max)) + ' All Deletion completed'Kamran ShahidPrinciple Engineer Development(MCSD.Net,MCPD.net) |
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-03-08 : 10:29:58
|
can you explain the logic behind using loop for deletion? why cant you apply set based logic instead? whats it that you're trying to iterate on?------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2012-03-08 : 10:33:42
|
The only "problem" with your existing code is that the WHILE...DELETE TOP (@chunksize) loops are unnecessary; you're deleting all the affected rows in a single transaction anyway. This won't affect or improve the log growth.I removed the loops and interstitial print statements and made a few minor tweaks, but this is essentially the same:SET NOCOUNT ONDECLARE @tvpJobKeys AS tvpJobKeysDECLARE @tvpProblamaticJobs AS tvpJobKeysDECLARE @NumberRecords INT, @RowCount INT = 0, @ID VARCHAR(8), @chunksize INT = 5000INSERT INTO @tvpJobKeysSELECT ID FROM MyMainTable WHERE imjIsDeleted = 1ORDER BY CAST(PQTRecordCount AS INT) DESCSELECT @NumberRecords = @@ROWCOUNTPRINT 'Total Number of soft deleted Job ' + CAST(@NumberRecords AS VARCHAR(MAX))WHILE @RowCount <= @NumberRecordsBEGIN BEGIN TRY BEGIN TRANSACTION SELECT TOP 1 @ID = ID FROM @tvpJobKeys UPDATE MyMainTable SET imjIsThisAReplicaJob = 0, imjReplicaJobCreateDuration = NULL, imjReplicaJobCreatedDate = NULL, imjReplicaParentID = NULL, imjIsUpgraded = 0 WHERE imjReplicaParentID = @ID DELETE FROM PieceDetailRecord WHERE fkID = @ID DELETE FROM PieceBarcodeRecord WHERE fkID = @ID DELETE FROM PackageQuantityRecord WHERE fkID = @ID DELETE FROM PostageAdjustmentRecord WHERE fkID = @ID DELETE FROM OriginalContainerIdentificationRecord WHERE fkID = @ID DELETE FROM MailPieceUnitRelationShipRecord WHERE fkID = @ID DELETE FROM IntelligentMailRangeRecord WHERE fkID = @ID DELETE FROM ContainerQuantityRecord WHERE fkID = @ID DELETE FROM MyMainTableError WHERE fkID = @ID DELETE FROM MyMainTable WHERE ID = @ID DELETE FROM @tvpJobKeys WHERE ID = @ID PRINT 'Job ' + @ID + ' ' + CAST(@RowCount AS VARCHAR(MAX)) PRINT CONVERT(char(19), GETDATE(), 120) + ' Job Deletion completed' PRINT '------------------------------------------------------------------------------------' COMMIT TRANSACTION SET @RowCount = @RowCount + 1 END TRY BEGIN CATCH DELETE FROM @tvpJobKeys WHERE ID = @ID INSERT INTO @tvpProblamaticJobs VALUES(@ID) END CATCH --CHECKPOINTENDPRINT CONVERT(char(19), GETDATE(), 120) + ' All Deletion completed' The fastest way to delete with minimal logging is to use SIMPLE recovery mode on your database. If you add a CHECKPOINT after each iteration of the outermost WHILE loop (I commented it out in my example), this will clear the log of active transactions and will minimize growth.If your tables have no foreign keys, AND you're deleting a substantial amount of data (more than 25% of the total) then an even faster way is to export the data you want to keep, TRUNCATE all the affected tables, then import that data back using bcp or BULK INSERT. Since the TRUNCATE TABLE operation is minimally logged this will reduce overall log growth to the lowest possible size. However it will cause your database to be unavailable while the operation runs. |
 |
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-03-08 : 10:38:19
|
the code has few fkIDs so i think foreignkeys do exist------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
kamii47
Constraint Violating Yak Guru
353 Posts |
Posted - 2012-03-09 : 00:27:15
|
Yes foreign keys do exists. Also suppose i doesn't have enough privileges to change the recovery model (which i found out as Full by default) then how can I best tweak above possible logic.Kamran ShahidPrinciple Engineer Development(MCSD.Net,MCPD.net) |
 |
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2012-03-09 : 06:34:25
|
What do you mean by "tweak"? If your main goal is to minimize log growth, there's little else you can do other than add transaction log backups to your script, or add a delay to allow a regularly scheduled log backup to run before you start the next iteration. |
 |
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-03-09 : 11:50:02
|
quote: Originally posted by kamii47 Yes foreign keys do exists. Also suppose i doesn't have enough privileges to change the recovery model (which i found out as Full by default) then how can I best tweak above possible logic.Kamran ShahidPrinciple Engineer Development(MCSD.Net,MCPD.net)
you still didnt explain why you're doing loop based delete?------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
kamii47
Constraint Violating Yak Guru
353 Posts |
Posted - 2012-03-12 : 01:28:36
|
I wanted to either delete whole Relational entity or not.That's why i first identify all the id's then loop through each of them in such a way that all data of an entity will delete or nonKamran ShahidPrinciple Engineer Development(MCSD.Net,MCPD.net) |
 |
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-03-12 : 10:13:00
|
quote: Originally posted by kamii47 I wanted to either delete whole Relational entity or not.That's why i first identify all the id's then loop through each of them in such a way that all data of an entity will delete or nonKamran ShahidPrinciple Engineer Development(MCSD.Net,MCPD.net)
then also it never calls for row by row deletionyou can use set based logic inside transaction to get all or none effect------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|