The Difference Between DBCC SHRINKDATABASE and DBCC SHRINKFILE, and What to Check Before Running Them
公開日 2026-08-13 · 更新日 2026-08-13 · 最終検証日 2026-08-13
結論
`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`.
この文書の適用条件
| 対象製品 | SQL Server / Amazon RDS for SQL Server / Azure SQL Managed Instance |
|---|---|
| 確認バージョン | SQL Server 2008 and later |
| 適用環境 | On-premises, EC2, Amazon RDS, Azure |
| 必要権限 | sysadmin fixed server role or db_owner fixed database role |
| 実行影響 | Involves moving pages and changing the file size. I/O increases while it runs, and access to the target object slows down |
| 再起動 | Not required |
| 最終検証日 | 2026-08-13 |
そのまま実行できるコマンド
- 対象
- 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.
結果の読み方
| 列 | 意味 | 確認するポイント |
|---|---|---|
| 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 |
こういう状況で使います
- 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
考えられる原因(可能性の高い順)
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.
確認手順
- 1
Check free space per file
参照のみCheck `free_mb` via `sys.database_files` and `FILEPROPERTY`. Shrinking accomplishes nothing if free space is small.
- 2
Distinguish data files from log files
参照のみUse `type_desc` to be clear about the target — the two have different criteria for judgment.
- 3
For a log, check `log_reuse_wait_desc`
参照のみIf it is not NOTHING, resolve that cause first. Shrinking comes after.
- 4
Record the fragmentation percentage before shrinking
低Run `sys.dm_db_index_physical_stats` in `LIMITED` mode to get a baseline for comparison.
- 5
Check the autogrowth setting
参照のみEstimate 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
参照のみIf `is_auto_shrink_on` is 1, first consider whether this setting is appropriate.
対応方法
すぐに実施できる低リスクの対応
Consider not shrinking at all
参照のみUnused 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
中This stops the fragmentation and delay caused by repeated shrink/grow cycles. It is disabled by default.
For a log, resolve the underlying cause first
低Shrink only after `log_reuse_wait_desc` reads NOTHING. Doing it in the reverse order accomplishes nothing.
事前検討が必要な変更
Shrink the log file with `TRUNCATEONLY`
高Since 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
中Setting 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
中A "%" 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
中Designing a move of old data to a separate table or filegroup lets you manage file size without relying on shrinking.
再起動・サービス影響を伴う変更
Shrink a data file
高Page 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`
高Every 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
高This 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.
!注意事項
- 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.
バージョン・環境による違い
これで解決しない場合に確認すること
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.
この文書の根拠と限界
製品の公式ドキュメントに基づく説明
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.
よくある質問
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.
この文書がカバーする質問
- 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
リスク表示の意味
- 参照のみデータと設定を変更しません。
- 低影響は限定的ですが、権限と負荷の確認が必要です。
- 中性能・ロック・コストに影響する可能性があります。
- 高障害・データ損失・復旧作業が発生する可能性があります。
- 専門家レビュー必須本番適用前に別途レビューが必須です。
GIIPの対応範囲
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.
執筆・技術検証
GIIP プロダクション運用チーム
大規模Webサービス、SQL Server、Oracle、AWS、Azureの設計・移行・運用に約30年従事。x12largeクラスのAWS RDS for SQL Server環境12セット、約12万テーブルのOracle環境、約3TBのTiDBからAurora MySQLへの移行を経験。現在も複数のクラウドデータベースと約30のWebサービスを、AIエージェントと人間の専門家が継続的に監視・運用しています。
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.
関連サービス
Design a permanent fix for file bloat
同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。
Design a permanent fix for file bloat