Ghost Records are logically deleted index records waiting for physical cleanup. I investigate their context before recommending an intervention.

A participant asked this question during my performance-tuning workshop. The distinction between a logical deletion and later physical cleanup was the starting point. It doesn’t make every cleanup command appropriate for routine use.
-- Select the intended database first and replace this schema-qualified table.
DECLARE @ObjectID int = OBJECT_ID(N'dbo.TestTable', N'U');
IF @ObjectID IS NULL THROW 50000, 'The specified table was not found.', 1;
SELECT DB_NAME(database_id) AS DatabaseName,
OBJECT_SCHEMA_NAME(object_id, database_id) AS SchemaName,
OBJECT_NAME(object_id, database_id) AS TableName,
index_id, partition_number, ghost_record_count, version_ghost_record_count
FROM sys.dm_db_index_physical_stats(DB_ID(), @ObjectID, NULL, NULL, 'DETAILED');Run the scoped diagnostic in the intended database. If OBJECT_ID returns NULL, passing it directly to the function would broaden the scan; this guard prevents that. DETAILED can read many pages and should be planned for the table size and workload. Results are per index, partition and allocation-unit context, not one universal database total.
The background ghost-cleanup task normally removes eligible records. Row versions, active transactions and workload conditions can delay reclamation. Inserts or updates don’t automatically make every record a ghost.
I previously recommended sp_clean_db_free_space before backups. That procedure scrubs residual information across data pages and can generate substantial I/O. It isn’t routine backup preparation or a lightweight ghost-clearing command. Use it for its documented purpose with an operational plan.
Reference: Residual-data cleanup scope.
Related reading
Ghost cleanup is not a backup prerequisite, it is background reclamation whose eligibility depends on the workload.
Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.
Discover more from SQL Authority with Pinal Dave
Subscribe to get the latest posts sent to your email.





6 Comments. Leave new
I would probably get rid of the ghost before I did a backup. But I also fold my trash neatly before I throw it out. :-) If you ever heard of obsessive compulsive disorder? Decades ago one of my favorite waitresses at a bar I went to on a regular basis would come by my table, unroll the napkin that I put in my glass to indicate I was finished, crumple it, and leave it on top. She knew it would drive me nuts. But eventually she got me over my OCD. :)
This is the one of the most interesting story Joe sir, I hope to meet you soon. It has been a long time.
One doubt sir ,if I create another db and then import export the data with all dependent objects then will these ghost record be ignored ?
does this query execution satisfy dod 5220.22m standards?
you need to ask from security experts who know what is DoD.
Hi Sir,
I had a scenario, in which deletion of records done on where conditions. the deletion is successful. when I run select statement with same where condition the record count is zero, but without where clause I can see all the record count(Which includes deleted and remaining). My total record count is 18 crore and deleting record count is 17 crore. Please let me know how it is possible to get all record count.