You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/relational-databases/ghost-record-cleanup-process-guide.md
+20-19Lines changed: 20 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,8 @@ title: "Ghost cleanup process guide"
3
3
description: Learn about the ghost cleanup process, a background process that deletes records off of pages that have been marked for deletion in SQL Server.
4
4
author: MashaMSFT
5
5
ms.author: mathoma
6
-
ms.date: "05/02/2018"
6
+
ms.reviewer: dfurman
7
+
ms.date: 12/07/2025
7
8
ms.service: sql
8
9
ms.subservice: supportability
9
10
ms.topic: conceptual
@@ -12,44 +13,44 @@ helpviewer_keywords:
12
13
- "ghost records"
13
14
- "ghost clean up process"
14
15
---
16
+
15
17
# Ghost cleanup process guide
16
18
17
-
The ghost cleanup process is a single-threaded background process that deletes records off of pages that have been marked for deletion. The following article provides an overview of this process.
19
+
The ghost cleanup process is a single-threaded background process that deletes records marked for deletion in data pages. The following article provides an overview of this process.
18
20
19
21
## Ghost records
20
22
21
-
Records that are deleted from a leaf level of an index page aren't physically removed from the page - instead, the record is marked as 'to be deleted', or *ghosted*. This means that the row stays on the page but a bit is changed in the row header to indicate that the row is really a ghost. This is to optimize performance during a delete operation. Ghosts are necessary for row-level locking, but are also necessary for snapshot isolation where we need to maintain the older versions of rows.
23
+
Records that are deleted from the leaf level of an index page aren't physically removed from the page. Instead, the record is marked as 'to be deleted', or *ghosted*. This means that the row stays on the page but a bit is changed in the row header to indicate that the row is a ghost. This is to optimize performance during a delete operation. Ghosts are necessary for row-level locking, but are also necessary for snapshot isolation where the database engine must maintain older row versions.
22
24
23
25
## Ghost record cleanup task
24
26
25
-
Records that are marked for deletion, or *ghosted*, are cleaned up by the background ghost cleanup process. This background process runs sometime after the delete transaction is committed, and physically removes ghosted records from pages. The ghost cleanup process runs automatically on an interval (every 5 seconds for SQL Server 2012+, every 10 seconds for SQL Server 2008/2008R2) and checks to see if any pages have been marked with ghost records. If it finds any, then it goes and deletes the records that are marked for deletion, or *ghosted*, touching at most 10 pages with each execution.
27
+
Records that are marked for deletion, or *ghosted*, are cleaned up by the background ghost cleanup process when they are no longer required. This background process runs after the delete transaction is committed and all row versions are no longer required, and physically removes ghosted records from pages. The ghost cleanup process runs periodically and checks to see if any pages have ghost records. If it finds any, it physically removes the records that are marked for deletion, or *ghosted*, touching at most 10 pages with each execution.
26
28
27
-
When a record is ghosted, the database is marked as having ghosted entries, and the ghost cleanup process will only scan those databases. The ghost cleanup process will also mark the database as 'having no ghosted records' once all ghosted records have been deleted, and it will skip this database the next time it runs. The process will also skip any databases it is unable to take a shared lock on, and will try again the next time it runs.
29
+
When a record is ghosted, the database is marked as having ghosted entries, and the ghost cleanup process only scans such databases. The ghost cleanup process also marks the database as having no ghosted records once all ghosted records have been removed, and skips this database the next time it runs. The process also skips any database if it can't acquire a shared lock on on the database. It retries acquiring the lock the next time it runs.
28
30
29
-
The below query can identify how many ghosted records exist in a single database.
31
+
The below query returns an approximate number of ghosted records in a database.
On high-load systems with many deletes, the ghost cleanup process can cause a performance issue from keeping pages in the buffer pool and generating IO. As such, it is possible to disable this process with the use of [trace flag 661](../t-sql/database-console-commands/dbcc-traceon-trace-flags-transact-sql.md). However, there are performance implications from disabling the process.
41
-
42
-
Disabling the ghost cleanup process can cause your database to grow unnecessarily large and can lead to performance issues. Since the ghost cleanup process removes records that are marked as ghosts, disabling the process will leave these records on the page, preventing SQL Server from reusing this space. This forces SQL Server to add data to new pages instead, leading to bloated database files, and can also cause [page splits](indexes/specify-fill-factor-for-an-index.md). Page splits lead to performance issues when creating execution plans, and when doing scan operations.
43
+
In rare cases in high-load systems with many deletes, the ghost cleanup process can cause a performance issue because it can replace the frequently accessed pages in the buffer pool with pages that have ghosted records, and generate extra IO load. If this occurs, you can temporarily disable this process with the use of [trace flag 661](../t-sql/database-console-commands/dbcc-traceon-trace-flags-transact-sql.md#tf661).
43
44
44
-
Once the ghost cleanup process is disabled, some action needs to be taken to remove the ghosted records. One option is to execute an index rebuild, which will move data around on pages. Another option is to manually run [sp_clean_db_free_space](system-stored-procedures/sp-clean-db-free-space-transact-sql.md) (to clean all database data files) or [sp_clean_db_file_free_space](system-stored-procedures/sp-clean-db-file-free-space-transact-sql.md) (to clean a single database datafile), which will delete ghosted records.
45
+
Disabling ghost cleanup permanently is not recommended. Without ghost cleanup, your database can grow unnecessarily large, which can lead to performance issues. Since the ghost cleanup process removes records that are marked as ghosts, disabling the process leaves these records on the page, preventing the database engine from reusing this space. This forces the database engine to add data to new pages instead, leading to bloated database files, and can also cause [page splits](indexes/specify-fill-factor-for-an-index.md). Page splits lead increase disk IO which can reduce query performance.
45
46
46
-
>[!warning]
47
-
> Disabling the ghost cleanup process is not generally recommended. Doing so should be tested thoroughly in a controlled environment before being implemented permanently in a production environment.
47
+
Once the ghost cleanup process is disabled, some action needs to be taken to remove the ghosted records. For example, you can rebuild indexes, which creates new pages from existing data, omitting ghosted records.
48
48
49
+
> [!WARNING]
50
+
> Disabling the ghost cleanup process is not recommended.
49
51
50
-
## Related content
52
+
## Related content
51
53
52
-
-[Remove ghost records from a single database file](system-stored-procedures/sp-clean-db-file-free-space-transact-sql.md)
53
-
-[Remove ghost records from all database data files](system-stored-procedures/sp-clean-db-free-space-transact-sql.md)
54
+
-[Pages and extents architecture guide](pages-and-extents-architecture-guide.md)
Removes residual information left on database pages because of data modification routines in [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)]. `sp_clean_db_file_free_space` cleans all pages in only one file of a database.
25
+
Removes residual information left on database pages. `sp_clean_db_file_free_space` cleans all pages in only one file of a database.
@@ -47,21 +48,21 @@ The data file ID to clean. *@fileid* is **int**, with no default.
47
48
48
49
#### [ @cleaning_delay = ]*cleaning_delay*
49
50
50
-
Specifies an interval to delay between the cleaning of pages. *@cleaning_delay* is **int**, with a default of `0`. This delay helps reduce the effect on the I/O system.
51
+
Specifies an interval to delay between the cleaning of pages. *@cleaning_delay* is **int**, with a default of `0`. This delay helps reduce the load on the I/O system.
51
52
52
53
## Return code values
53
54
54
55
`0` (success) or `1` (failure).
55
56
56
57
## Remarks
57
58
58
-
Deletes operations from a table or update operations that cause a row to move can immediately free up space on a page by removing references to the row. However, under certain circumstances, the row can physically remain on the data page as a ghost record. A background process periodically removes ghost records. This residual data isn't returned by the [!INCLUDE [ssDE](../../includes/ssde-md.md)] in response to queries. However, in environments in which the physical security of the data or backup files is at risk, you can use `sp_clean_db_file_free_space` to clean these ghost records. To perform this operation for all database files at once, use [sp_clean_db_free_space](sp-clean-db-free-space-transact-sql.md).
59
+
The `sp_clean_db_free_space` system stored procedure moves all rows on a page, including the ghosted records if any, to the beginning of the page and then zero-initializes the remainder of the space on the page. In environments where the physical security of the data files is at risk, you can use this stored procedure to ensure that no residual deleted data remain in the data files.
59
60
60
-
The length of time required to run `sp_clean_db_file_free_space` depends on the size of the file, the available free space, and the capacity of the disk. Because running `sp_clean_db_file_free_space` can significantly affect I/O activity, we recommend that you run this procedure outside usual operation hours.
61
+
The time required to run `sp_clean_db_file_free_space` depends on the size of the data file, the number of used pages in the file, and the I/O capabilities of the disk. Because running `sp_clean_db_file_free_space` can significantly increase I/O activity, we recommend that you run this procedure outside the usual operation hours.
61
62
62
63
Before you run `sp_clean_db_file_free_space`, we recommend that you create a full database backup.
63
64
64
-
The related [sp_clean_db_free_space](sp-clean-db-free-space-transact-sql.md) stored procedure cleans all files in the database.
65
+
To perform this operation for all data files in a database, use [sp_clean_db_free_space](sp-clean-db-free-space-transact-sql.md).
Removes residual information left on database pages because of data modification routines in [!INCLUDE [ssNoVersion](../../includes/ssnoversion-md.md)].`sp_clean_db_free_space` cleans all pages in all files of the database.
25
+
Removes residual information left on database pages.`sp_clean_db_free_space` cleans all pages in all data files of the database.
@@ -42,29 +43,29 @@ The name of the database to clean. *@dbname* is **sysname**, with no default.
42
43
43
44
#### [ @cleaning_delay = ]*cleaning_delay*
44
45
45
-
Specifies an interval to delay between the cleaning of pages. *@cleaning_delay* is **int**, with a default of `0`. This delay helps reduce the effect on the I/O system.
46
+
Specifies an interval to delay between the cleaning of pages. *@cleaning_delay* is **int**, with a default of `0`. This delay helps reduce the load on the I/O system.
46
47
47
48
## Return code values
48
49
49
50
`0` (success) or `1` (failure).
50
51
51
52
## Remarks
52
53
53
-
Delete operations from a table or update operations that cause a row to move can immediately free up space on a page by removing references to the row. However, under certain circumstances, the row can physically remain on the data page as a ghost record. A background process periodically removes ghost records. This residual data isn't returned by the [!INCLUDE [ssDE](../../includes/ssde-md.md)] in response to queries. However, in environments in which the physical security of the data or backup files is at risk, you can use `sp_clean_db_free_space` to clean these ghost records. To perform this operation per database file, use [sp_clean_db_file_free_space](sp-clean-db-file-free-space-transact-sql.md).
54
+
The `sp_clean_db_free_space` system stored procedure moves all rows on a page, including the ghosted records if any, to the beginning of the page and then zero-initializes the remainder of the space on the page. In environments where the physical security of the data files is at risk, you can use this stored procedure to ensure that no residual deleted data remain in the data files.
54
55
55
-
The length of time required to run `sp_clean_db_free_space` depends on the size of the file, the available free space, and the capacity of the disk. Because running `sp_clean_db_free_space` can significantly affect I/O activity, we recommend that you run this procedure outside usual operation hours.
56
+
The time required to run `sp_clean_db_free_space` depends on the size of the data files, the number of used pages in the files, and the I/O capabilities of the disk. Because running `sp_clean_db_free_space` can significantly increase I/O activity, we recommend that you run this procedure outside the usual operation hours.
56
57
57
58
Before you run `sp_clean_db_free_space`, we recommend that you create a full database backup.
58
59
59
-
The related [sp_clean_db_file_free_space](sp-clean-db-file-free-space-transact-sql.md) stored procedure can clean a single file.
60
+
To perform this operation per database file, use [sp_clean_db_file_free_space](sp-clean-db-file-free-space-transact-sql.md).
60
61
61
62
## Permissions
62
63
63
64
Requires membership in the `db_owner` database role.
64
65
65
66
## Examples
66
67
67
-
The following example cleans all residual information from the [!INCLUDE [sssampledbobject-md](../../includes/sssampledbobject-md.md)] database.
68
+
The following example cleans all residual data from the [!INCLUDE [sssampledbobject-md](../../includes/sssampledbobject-md.md)] database.
0 commit comments