Optimizing Delete on SQL Server
Solution 1:
The following article, Fast Ordered Delete Operations may be of interest to you.
Performing fast SQL Server delete operations
The solution focuses on utilising a view in order to simplify the execution plan produced for a batched delete operation. This is achieved by referencing the given table once, rather than twice which in turn reduces the amount of I/O required.
Solution 2:
I have much more experience with Oracle, but very likely the same applies to SQL Server as well:
- when deleting a large number of rows, issue a table lock, so the database doesn't have to do lots of row locks
- if the table you delete from is referenced by other tables, make sure those other tables have indexes on the foreign key column(s) (otherwise the database will do a full table scan for each deleted row on the other table to ensure that deleting the row doesn't violate the foreign key constraint)
Solution 3:
I wonder if it's time for garbage-collecting databases? You mark a row for deletion and the server deletes it later during a sweep. You wouldn't want this for every delete - because sometimes a row must go now - but it would be handy on occasion.
Solution 4:
Summary of Answers through 2014-11-05
This answer is flagged as community wiki since this is an ever-evolving topic with a lot of nuances, but very few possible answers overall.
The first issue is you must ask yourself what scenario you're optimizing for? This is generally either performance with a single user on the db, or scale with many users on the db. Sometimes the answers are the exact opposite.
For single user optimization
- Hint a
TABLELOCK
- Remove indexes not used in the delete then rebuild them afterward
- Batch using something like
SET ROWCOUNT 20000
(or whatever, depending on log space) and loop (perhaps with aWAITFOR DELAY
) until you get rid of it all (@@ROWCOUNT = 0
) - If deleting a large % of table, just make a new one and delete the old table
- Partition the rows to delete, then drop the parition. [Read more...]
For multi user optimization
- Hint row locks
- Use the clustered index
- Design clustered index to minimize page re-organization if large blocks are deleted
- Update "is_deleted" column, then do actual deletion later during a maintenance window
For general optimization
- Be sure FKs have indexes on their source tables
- Be sure
WHERE
clause has indexes - Identify the rows to delete in the
WHERE
clause with a view or derived table instead of referencing the table directly. [Read more...]