As things stand, the query:
DELETE TOP (4000)
FROM [OLD_TABLE] WITH (TABLOCKX)
WHERE [Date] < '2014-01-01 00:00:00'
...has to scan the whole heap table, testing each row it finds, until it eventually finds 4000 to delete. On the next iteration, the whole business starts again from square one. Assuming the scanning process is performed in the same (allocation unit) order each time, these scans will take longer and longer to find 4000 rows as time goes by.
Creating an index on the [Date]
column will allow SQL Server to find the 4000 rows much more efficiently. It does add a small overhead to each delete (as the new nonclustered index needs to be maintained as well) but this is nothing compared to the effort that will be saved by not performing a scan each time. The index will also require a certain amount of space, but it should not be too large. You should create the following index before resuming your data removal process:
CREATE NONCLUSTERED INDEX <index_name>
ON dbo.OLD_TABLE ([Date]);
By the way, if the database has snapshot isolation or read committed snapshot isolation enabled (even if not actively used!), the TABLOCKX
hint will not be enough to ensure that empty heap pages are deallocated. Your heap table may therefore contain many empty pages - a concern since you are so low on space.
The standard way to address this space management issue is to create a clustered index (or issue an ALTER TABLE REBUILD
statement, but that requires SQL Server 2008). It seems that creating a clustered index might also not be an option for you, due to space constraints. There isn't an obvious way to resolve this right now, given the space issue.
One thing to keep an eye on while the delete is progressing is the space used by the transaction log. If the database is in FULL
or BULK_LOGGED
recovery, you will need to keep on top of backing up the log. If the database is using SIMPLE
recovery, you may need to issue a manual CHECKPOINT
from time to time to release transaction log space for reuse (otherwise the physical file might grow).
If you can get hold of some additional temporary storage, a better way might be to bulk export the data you want to keep to a safe location, drop the table, recreate it (preferably with a clustered index!) and reload the saved data. This is generally faster than the incremental-delete process, but it depends on your objectives and priorities.
I've calculated that, at the peak, the average amount of records is somewhere in the avenue of 3-4 billion per day (20 hours of operation).
From your screenshot, you ONLY have 8GB memory total RAM and 6 GB allocated to SQL Server. This is way tooo low for what you are trying to achieve.
I suggest you to upgrade the memory to a higher value - 256GB and bump up your VM CPUs as well.
You need to invest in hardware at this point for your workload.
Also refer to data loading performance guide - it describes smart ways of efficiently loading the data.
My tempdb is 8mb.
Based on your edit .. you should have a sensible tempdb - preferably multiple tempdb data files equally sized along with TF 1117 and 1118 enabled instance wide.
I would suggest you to get a professional health check and start from there.
Highly recommend
Bump up your server spec.
Get a professional* person do a health check of your database server instance and follow the recommendations.
Once a. and b. are done, then immerse yourself in query tuning and other optimizations like looking at wait stats, query plans, etc.
Note: I am a professional sql server expert at hackhands.com - a pluralsight company, but in no means suggesting you to hire me for help. I am merely suggesting you to take professional help based on your edits only.
HTH.
Best Answer
one option (if feasible for you considering the downside) would be to change the database to bulk logging and bcp into the target table from a view reading the source tables. the actual logging should be minimized, but the log backup will still be huge as it will include the changed extents. a downside of bulk logging is that is compromises the ability to point in time recover to a time frame during the bulk logging operation. make sure you take a log backup immediately after the bulk import