The Difference Between DBCC SHRINKDATABASE and DBCC SHRINKFILE, and What to Check Before Running Them
Published 2026-08-13 · Updated 2026-08-13 · Last Verified 2026-08-13
Answer
`DBCC SHRINKDATABASE` targets every file in the database, while `DBCC SHRINKFILE` targets only the one file you specify. Shrinking a data file moves pages around, so index fragmentation increases significantly afterward — this is not an operation that belongs in routine maintenance. Shrinking a log file, on the other hand, can be a reasonable way to reverse a temporary bloat, but only after you have resolved whatever is behind `log_reuse_wait_desc`.
Applicability of This Document
| Product | SQL Server / Amazon RDS for SQL Server / Azure SQL Managed Instance |
|---|---|
| Verified Versions | SQL Server 2008 and later |
| Environment | On-premises, EC2, Amazon RDS, Azure |
| Required Permissions | sysadmin fixed server role or db_owner fixed database role |
| Execution Impact | Involves moving pages and changing the file size. I/O increases while it runs, and access to the target object slows down |
| Restart | Not required |
| Last Verified | 2026-08-13 |
Ready-to-Run Commands
- 対象
- SQL Server 2008 and later / Amazon RDS for SQL Server
- 権限
- Connection permission to the target DB
- 変更作業
- None (read-only)
- Production実行
- Safe to run
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: 対象DBへの接続権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
USE [SampleDB];
GO
SELECT
f.file_id,
f.name AS logical_name,
f.type_desc, -- ROWS(データ)/ LOG(ログ)
f.physical_name,
f.size * 8 / 1024 AS size_mb,
CAST(FILEPROPERTY(f.name, 'SpaceUsed') AS bigint) * 8 / 1024 AS used_mb,
(f.size - CAST(FILEPROPERTY(f.name, 'SpaceUsed') AS bigint)) * 8 / 1024 AS free_mb,
CASE
WHEN f.is_percent_growth = 1 THEN CAST(f.growth AS varchar(10)) + ' %'
ELSE CAST(f.growth * 8 / 1024 AS varchar(10)) + ' MB'
END AS autogrowth,
CASE
WHEN f.max_size IN (-1, 268435456) THEN NULL
ELSE f.max_size * 8 / 1024
END AS max_size_mb
FROM sys.database_files AS f
ORDER BY f.type_desc, f.file_id;First check whether there is actually any free space. Shrinking a file with a small `free_mb` accomplishes nothing — only unused space can be reclaimed.
- 対象
- SQL Server 2008 and later / Amazon RDS for SQL Server
- 権限
- Metadata visibility on `sys.databases`
- 変更作業
- None (read-only)
- Production実行
- Safe to run
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: sys.databases のメタデータ可視性
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
name AS database_name,
recovery_model_desc,
log_reuse_wait_desc,
is_auto_shrink_on
FROM sys.databases
WHERE database_id > 4
ORDER BY name;Shrinking the log while `log_reuse_wait_desc` is anything other than NOTHING just means it grows right back, as long as that underlying cause remains. The prerequisite for shrinking the log is that this column reads NOTHING. If `is_auto_shrink_on` is 1, auto-shrink is enabled — consider disabling it.
- 対象
- SQL Server 2008 and later / Amazon RDS for SQL Server
- 権限
- sysadmin or db_owner
- 変更作業
- Yes (returns unused space at the end of the file to the OS)
- Production実行
- Can be run, but requires `log_reuse_wait_desc` to be resolved first
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: sysadmin または db_owner
-- 変更作業: あり(ファイル末尾の未使用領域を OS に返却)
-- Production 実行: 可能。ただし log_reuse_wait_desc が NOTHING であることが前提
USE [SampleDB];
GO
-- 末尾の未使用領域だけを解放する(ページ移動を伴わない)
DBCC SHRINKFILE (N'SampleDB_log', TRUNCATEONLY);
-- 目標サイズ(MB)を指定して縮小する
-- DBCC SHRINKFILE (N'SampleDB_log', 1024);`TRUNCATEONLY` only releases unused space at the end of the file and does not move any data. For a log file, depending on how its virtual log files (VLFs) are being used, the tail may still be in use and not shrink as expected — in that case, re-run it after a log backup or a checkpoint. Note that this knowledge base displays every SHRINK-family operation as "high" risk regardless of its actual impact, as a policy to prevent running it without a pre-check — it does not mean this particular operation carries the same impact as a target-size shrink.
- 対象
- SQL Server 2008 and later / Amazon RDS for SQL Server
- 権限
- sysadmin or db_owner
- 変更作業
- Yes (moves pages to shrink the file; index fragmentation increases)
- Production実行
- Not allowed as a rule. If done, pair it with a maintenance window and a rebuild plan
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: sysadmin または db_owner
-- 変更作業: あり(ページ移動によりインデックス断片化が大きく進む)
-- Production 実行: 原則不可。メンテナンス時間帯+事後のインデックス再構築が前提
USE [SampleDB];
GO
-- 目標サイズ(MB)を指定してデータファイルを縮小する
DBCC SHRINKFILE (N'SampleDB', 8192);
-- 末尾の未使用領域だけを返す(ページ移動なし・断片化の影響が小さい)
-- DBCC SHRINKFILE (N'SampleDB', TRUNCATEONLY);A shrink with a target size moves pages at the end of the file into free space before truncating the tail. This movement disrupts the logical ordering and significantly increases index fragmentation. `TRUNCATEONLY`, which returns only the tail, does not move pages, so its impact in terms of fragmentation is smaller.
- 対象
- SQL Server 2008 and later / Amazon RDS for SQL Server
- 権限
- sysadmin or db_owner
- 変更作業
- Yes (moves pages and shrinks every file in the database)
- Production実行
- Not allowed as a rule. If done, expect an impact equivalent to a business outage
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: sysadmin または db_owner
-- 変更作業: あり(全ファイル対象のページ移動と縮小)
-- Production 実行: 原則不可。業務停止相当の影響を見込み、事後の再構築計画を用意すること
USE [SampleDB];
GO
-- 第2引数は「縮小後にファイルに残す空き領域の割合(%)」
DBCC SHRINKDATABASE (N'SampleDB', 10);
-- 末尾の未使用領域だけを返す
-- DBCC SHRINKDATABASE (N'SampleDB', TRUNCATEONLY);`DBCC SHRINKDATABASE` targets every file (data and log) in the database. Because you cannot pick which file it touches, its impact is hard to predict — in practice, handling files one at a time with `DBCC SHRINKFILE` is easier to control. The second argument, `target_percent`, is "the percentage of free space to leave after shrinking," not a shrink ratio.
- 対象
- SQL Server 2008 and later / Amazon RDS for SQL Server
- 権限
- Connection permission to the target DB and VIEW DATABASE STATE
- 変更作業
- None (read-only, but reading pages generates I/O)
- Production実行
- Safe to run — use `LIMITED` mode
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: 対象DBへの接続権限と VIEW DATABASE STATE
-- 変更作業: なし(参照のみ。ただしページを読むため I/O が発生する)
-- Production 実行: 可能。DETAILED は負荷が高いため LIMITED を使うこと
USE [SampleDB];
GO
SELECT
OBJECT_SCHEMA_NAME(ips.object_id) AS schema_name,
OBJECT_NAME(ips.object_id) AS table_name,
i.name AS index_name,
ips.index_type_desc,
ips.avg_fragmentation_in_percent,
ips.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') AS ips
INNER JOIN sys.indexes AS i
ON ips.object_id = i.object_id
AND ips.index_id = i.index_id
WHERE ips.page_count > 1000 -- 小さいインデックスは断片化の影響が小さい
ORDER BY ips.avg_fragmentation_in_percent DESC;Run the same query before and after shrinking and compare the change in `avg_fragmentation_in_percent`. `DETAILED` mode reads every page and is expensive, so use `LIMITED` in production.
- 対象
- SQL Server 2008 and later / Amazon RDS for SQL Server
- 権限
- sysadmin or db_owner (ALTER permission)
- 変更作業
- Yes (changes a database option)
- Production実行
- Can be run — manage disabling it as a database option change
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: sysadmin または db_owner(ALTER 権限)
-- 変更作業: あり(データベースオプションの変更)
-- Production 実行: 可能。変更管理の手順に従うこと
ALTER DATABASE [SampleDB] SET AUTO_SHRINK OFF;
-- 現在の設定を確認する(参照のみ)
SELECT name, is_auto_shrink_on
FROM sys.databases
WHERE database_id > 4;AUTO_SHRINK is disabled by default. If it is enabled, shrinking and autogrowth repeat in a cycle, each time causing fragmentation from page movement and a write delay while growth completes. If it is enabled, consider disabling it.
How to Read the Results
| Column | Meaning | What to Check |
|---|---|---|
| type_desc | File type (ROWS / LOG) | Whether shrinking makes sense is entirely different for data files versus log files |
| size_mb | The file's current size | Record this value before shrinking |
| used_mb | Space actually in use | This is the floor you can shrink to — set the target size larger than this |
| free_mb | Unused space | If small, shrinking accomplishes nothing — use this to decide whether to bother at all |
| autogrowth | The autogrowth setting | Check whether the growth increment is reasonable, given that regrowth is likely after shrinking |
| log_reuse_wait_desc | Reason the log cannot be reused | Shrinking the log is pointless unless this is NOTHING — resolve the cause first |
| is_auto_shrink_on | Whether auto-shrink is enabled | If 1, consider disabling it — it causes a cycle of shrinking and growing |
| avg_fragmentation_in_percent | An index's average fragmentation | Compare before and after shrinking — a large increase means a rebuild is needed |
| page_count | An index's page count | An index with few pages has little impact even at a high fragmentation percentage |
When to Use This
- Disk free space is shrinking, and you want to make the database files smaller
- A data file's size did not change even after a large delete
- A temporary process bloated a log file, and you want to shrink it back
- A scheduled shrink job is in place for routine maintenance, but performance keeps gradually degrading
Possible Causes (Most Likely First)
01
Unused space left after a large delete or archive
Deleting data does not automatically shrink the file. The space remains as unused and gets reused by subsequent writes. This state is usually not a problem, and shrinking is not always necessary.
02
Log bloat from a temporary process
A large data migration or bulk update can temporarily grow the log. If the process has finished and the size is permanently unneeded, shrinking the log is a reasonable action.
03
A factor preventing the log from being released still remains
This includes an open transaction, stopped CDC or replication, or missing log backups. In this state, the log will grow back even after shrinking.
04
AUTO_SHRINK is enabled
With auto-shrink enabled, shrinking and autogrowth repeat in a cycle, each time causing fragmentation from page movement and write delays while growth completes. It is disabled by default, and there is rarely a good reason to turn it on.
05
Shrinking has been built into routine maintenance
This is a loop of shrink → fragment → rebuild → file growth → shrink. It only consumes I/O and never leads to a lasting improvement.
Diagnostic Steps
- 1
Check free space per file
Read-onlyCheck `free_mb` via `sys.database_files` and `FILEPROPERTY`. Shrinking accomplishes nothing if free space is small.
- 2
Distinguish data files from log files
Read-onlyUse `type_desc` to be clear about the target — the two have different criteria for judgment.
- 3
For a log, check `log_reuse_wait_desc`
Read-onlyIf it is not NOTHING, resolve that cause first. Shrinking comes after.
- 4
Record the fragmentation percentage before shrinking
LowRun `sys.dm_db_index_physical_stats` in `LIMITED` mode to get a baseline for comparison.
- 5
Check the autogrowth setting
Read-onlyEstimate the cost of regrowth after shrinking. A "%" setting grows by a larger amount each time as the file gets bigger.
- 6
Check the AUTO_SHRINK setting
Read-onlyIf `is_auto_shrink_on` is 1, first consider whether this setting is appropriate.
Solutions
Low-risk action that can be done immediately
Consider not shrinking at all
Read-onlyUnused space gets reused by subsequent writes. If there is headroom in storage capacity, not shrinking is the safest and cheapest choice.
Disable AUTO_SHRINK if it is enabled
MediumThis stops the fragmentation and delay caused by repeated shrink/grow cycles. It is disabled by default.
For a log, resolve the underlying cause first
LowShrink only after `log_reuse_wait_desc` reads NOTHING. Doing it in the reverse order accomplishes nothing.
Change requiring advance review
Shrink the log file with `TRUNCATEONLY`
HighSince it involves no page movement, this has a smaller impact than shrinking a data file. Do this only after resolving whatever was behind `log_reuse_wait_desc`. Since every SHRINK-family operation is shown as "high" risk, do not skip the pre-check.
Set a target size that leaves room for regrowth
MediumSetting the target size right at the current usage triggers autogrowth almost immediately, delaying writes. Leave the headroom your normal operation actually needs.
Change autogrowth to a fixed MB value
MediumA "%" setting grows by a larger amount each time the file gets bigger. A fixed MB value is easier to predict.
Control size permanently through archiving and partitioning
MediumDesigning a move of old data to a separate table or filegroup lets you manage file size without relying on shrinking.
Change involving a restart or service impact
Shrink a data file
HighPage movement significantly increases index fragmentation. If you do this, it assumes a plan that includes the subsequent index rebuild along with its duration and the resulting log growth.
Run `DBCC SHRINKDATABASE`
HighEvery file in the database is targeted, and you cannot control the scope of impact. Consider first whether `DBCC SHRINKFILE` per file can substitute for this.
Rebuild indexes after shrinking
HighThis reverses the fragmentation, but the rebuild grows the file again — a contradiction with the goal of "shrink to make it smaller" that you should understand before planning this.
!Warnings
- Shrinking a data file moves pages, so index fragmentation increases significantly afterward. This is not an operation to build into routine maintenance.
- A loop of shrink → fragment → rebuild → file growth only consumes I/O and never produces a lasting improvement — note that a rebuild grows the file again.
- `DBCC SHRINKDATABASE` targets every file in the database. Since you cannot choose the target, prefer `DBCC SHRINKFILE`, which lets you control things file by file.
- `DBCC SHRINKDATABASE`'s second argument is "the percentage of free space to leave after shrinking," not a shrink ratio. Specifying it incorrectly produces an unintended size.
- Shrink a log file only after `log_reuse_wait_desc` reads NOTHING. If the cause remains, the log will grow back even after shrinking.
- AUTO_SHRINK is disabled by default. Enabling it causes a cycle of shrinking and growing, leading to fragmentation and write delays. Enabling it is not recommended.
- Shrinking consumes significant I/O while running and slows down access to the target object. If interrupted mid-run, pages already moved are not undone.
- Setting the target size right at current usage triggers autogrowth immediately afterward. Since writes are delayed while growth happens, leave the headroom your normal operation needs.
Differences by Version and Environment
If This Doesn't Resolve It
Index fragmentation after shrinking
Compare before and after in `LIMITED` mode to identify the range needing a rebuild.
Actual free space on the storage side
With cloud block storage, shrinking a database file does not necessarily reduce the allocated storage capacity automatically.
History of autogrowth events
Check the default trace or the logs for repeated growth after a shrink.
Filegroups and data placement
If there are multiple filegroups, check which file has a disproportionate amount of free space before deciding on a target.
Basis and Limitations of This Document
Explanation based on official product documentation
A general procedure based on the public specifications of SQL Server's `DBCC SHRINKDATABASE` / `DBCC SHRINKFILE` (including `TRUNCATEONLY`), `sys.database_files`, `FILEPROPERTY`, `sys.dm_db_index_physical_stats`, and `ALTER DATABASE ... SET AUTO_SHRINK`. The degree of fragmentation caused by shrinking depends on data placement, so no specific figures are given. Reflecting a shrink in storage capacity on Amazon RDS assumes verification on the target environment.
FAQ
Should I use SHRINKDATABASE or SHRINKFILE?
In practice, `DBCC SHRINKFILE` is recommended. `DBCC SHRINKDATABASE` targets every file in the database, so you cannot control which file shrinks by how much. With `DBCC SHRINKFILE`, you specify the target file and size, keeping the scope of impact limited.
Why is shrinking a data file discouraged?
A shrink with a target size moves pages at the end of the file into free space before truncating the tail. This movement disrupts the logical ordering, significantly increasing index fragmentation. On top of that, the subsequent regrowth and the later rebuild both consume I/O, so it never produces a lasting improvement.
Is shrinking a log file fine, then?
It's a different situation from a data file — reversing bloat caused by a temporary process is a reasonable action. But this assumes `log_reuse_wait_desc` reads NOTHING; shrinking while the cause remains just leads to regrowth.
What is TRUNCATEONLY?
An option that returns only the unused space at the end of the file to the OS. Since it involves no page movement, its impact on fragmentation is smaller than a target-size shrink. However, if the tail is still in use, it may not shrink as much as expected.
Can this be run in production?
The check queries are read-only and can be run in production. Shrinking a data file and `DBCC SHRINKDATABASE` should not be done in production as a rule; if necessary, pair them with a maintenance window and a post-shrink index rebuild plan. `TRUNCATEONLY` on a log file can be done once the underlying cause has been resolved.
Does this work on AWS RDS?
`DBCC SHRINKFILE` is generally runnable with db_owner permission. However, shrinking a database file does not necessarily reduce the storage capacity allocated on RDS automatically. Check how this is handled on the storage side for your target environment.
Questions This Document Covers
- I want to make a data file smaller in SQL Server
- I want to know why shrinking degrades performance
- I want to know how to shrink only the log file
What the Risk Labels Mean
- Read-onlyDoes not change data or settings.
- LowImpact is limited, but permissions and load should be checked.
- MediumMay affect performance, locking, or cost.
- HighMay cause an outage, data loss, or require recovery work.
- Expert Review RequiredRequires a separate review before applying to production.
GIIP's Scope of Support
Shrinking a file looks like a one-time action, but it actually comes with downstream effects — fragmentation, regrowth, and increased I/O. At GIIP, we keep file size and usage, index fragmentation, and autogrowth events on the same timeline, so we can trace exactly what changed before and after a shrink. Because shrinking is high-impact and irreversible, it is excluded from automatic execution by an AI agent — the decision to act and the timing are left to a human.
Author & Technical Review
GIIP Production Operations Team
About 30 years of experience in designing, migrating, and operating large-scale web services, SQL Server, Oracle, AWS, and Azure. Experience includes 12 sets of x12large-class AWS RDS for SQL Server environments, an Oracle environment with roughly 120,000 tables, and migrating roughly 3TB from TiDB to Aurora MySQL. AI agents and human experts currently continue to monitor and operate multiple cloud databases and about 30 web services.
How to Check Transaction Log Usage on RDS for SQL Server
A read-only procedure that checks log usage with DBCC SQLPERF(LOGSPACE) and sys.dm_db_log_space_usage, and isolates the reason it is not being released using log_reuse_wait_desc.
sql-serverSQL to Check Statistics Last-Updated Time per Table in SQL Server
A read-only SQL script using sys.stats and STATS_DATE that lists the last-updated time and the number of rows modified since the last update, per table and statistic.
sql-serverSQL to Check for Long-Running Open Transactions in SQL Server
A procedure using the sys.dm_tran_active_transactions family of DMVs to identify abandoned transactions, including start time, session, and the last SQL statement executed.
infrastructureWhat's the Difference Between EBS IOPS and Physical Disk IOPS
A document organizing why EBS IOPS cannot be compared directly to physical disk IOPS, based on where the ceiling applies (volume vs. instance) and how to measure it.
Related Services
Design a permanent fix for file bloat
If you need to repeat the same checks across multiple environments, we can discuss your entire operations setup.
Design a permanent fix for file bloat