giip
SES Proposal
SQL Serverストレージログファイルインデックス性能

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

そのまま実行できるコマンド

Pre-check: usage and free space per file (read-only)参照のみ
対象
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.

Pre-check: why the log is not being released (a prerequisite for shrinking the log)参照のみ
対象
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.

Truncate the tail of a log file (TRUNCATEONLY — no data movement)
対象
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.

Shrink a data file (discouraged as a rule — causes fragmentation)
対象
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.

Shrink the entire database (the broadest impact)
対象
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.

Post-check: index fragmentation state
対象
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.

Disable AUTO_SHRINK
対象
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_descFile type (ROWS / LOG)Whether shrinking makes sense is entirely different for data files versus log files
size_mbThe file's current sizeRecord this value before shrinking
used_mbSpace actually in useThis is the floor you can shrink to — set the target size larger than this
free_mbUnused spaceIf small, shrinking accomplishes nothing — use this to decide whether to bother at all
autogrowthThe autogrowth settingCheck whether the growth increment is reasonable, given that regrowth is likely after shrinking
log_reuse_wait_descReason the log cannot be reusedShrinking the log is pointless unless this is NOTHING — resolve the cause first
is_auto_shrink_onWhether auto-shrink is enabledIf 1, consider disabling it — it causes a cycle of shrinking and growing
avg_fragmentation_in_percentAn index's average fragmentationCompare before and after shrinking — a large increase means a rebuild is needed
page_countAn index's page countAn 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

考えられる原因(可能性の高い順)

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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. 1

    Check free space per file

    参照のみ

    Check `free_mb` via `sys.database_files` and `FILEPROPERTY`. Shrinking accomplishes nothing if free space is small.

  2. 2

    Distinguish data files from log files

    参照のみ

    Use `type_desc` to be clear about the target — the two have different criteria for judgment.

  3. 3

    For a log, check `log_reuse_wait_desc`

    参照のみ

    If it is not NOTHING, resolve that cause first. Shrinking comes after.

  4. 4

    Record the fragmentation percentage before shrinking

    Run `sys.dm_db_index_physical_stats` in `LIMITED` mode to get a baseline for comparison.

  5. 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. 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.

バージョン・環境による違い

SQL Server 2008 and later`DBCC SHRINKDATABASE` / `DBCC SHRINKFILE` and the `TRUNCATEONLY`, `NOTRUNCATE`, and `EMPTYFILE` options are available.
SQL Server 2019 and laterSome versions support a shrink with the `RESUMABLE` option. Check availability on your target environment's version (verify before relying on this).
Amazon RDS for SQL Server`DBCC SHRINKFILE` is generally runnable with db_owner permission, but verify on the target environment whether it can be run and how it reflects on the storage side (including the fact that allocated storage does not automatically shrink) (verify before relying on this).

これで解決しない場合に確認すること

  • 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エージェントと人間の専門家が継続的に監視・運用しています。

関連するナレッジ

関連サービス

Design a permanent fix for file bloat

同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。

Design a permanent fix for file bloat

ナレッジベース一覧へ