Changing the locking to table locks will just make the deletes run even slower as the delete won't be able to run until the lock can be taken on the table which means that all other threads need to be finished or blocked. If you have foreign keys with delete cascade enabled that will probably take a lot of the time.
You might want to change it to a SQL Agent job so instead of running your app which connects and disconnects, you just run a loop deleting data until you are done.
SELECT NULL --Makes the WHILE loop work.
WHILE @@ROWCOUNT <> 0
BEGIN
DELETE TOP (1000) FROM YourTable
WHERE Column < getdate()-31
END
If this doesn't work you could look into table partitioning which would allow you to switch the data to another table very quickly, then truncate the data from the new table. This however does require Enterprise Edition.
You're going to have to physically move the data - there is no getting around that. But I don't know who came up with the idea that doing so requires creating a clustered index - this just exchanges certain steps for others, and isn't going to require any different amounts of temporary space to accomplish than the method I outline below.
Why not create a second, empty heap on the new filegroup:
CREATE TABLE dbo.whatever_copy
(
... cols ...
)
ON [second filegroup];
Then script the indexes, constraints etc. from the original table, copy the data over, remove any constraints that need to be removed (e.g. foreign keys pointing to the original table), then drop the original table, and rename the new one. Finally, add the indexes and constraints to the new table.
-- script out indexes, constraints etc.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
INSERT dbo.whatever_copy(cols) WITH (TABLOCK)
SELECT cols FROM dbo.whatever;
-- remove constraints etc.
DROP TABLE dbo.whatever;
EXEC sp_rename N'dbo.whatever_copy', N'whatever', N'OBJECT';
-- add constraints etc.
COMMIT TRANSACTION;
Best Answer
Sure, put a clustered index on it. Tables with a clustered index will automatically deallocate space.
Otherwise, you're looking at:
I know some folks think it's trendy, but heaps just aren't a good fit for active OLTP systems that have to deal with deletes (which cause the empty space problem) and updates (which cause the forwarded fetches problem.)