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

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

ProductSQL Server / Amazon RDS for SQL Server / Azure SQL Managed Instance
Verified VersionsSQL Server 2008 and later
EnvironmentOn-premises, EC2, Amazon RDS, Azure
Required Permissionssysadmin fixed server role or db_owner fixed database role
Execution ImpactInvolves moving pages and changing the file size. I/O increases while it runs, and access to the target object slows down
RestartNot required
Last Verified2026-08-13

Ready-to-Run Commands

Pre-check: usage and free space per file (read-only)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)Read-only
対象
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)High
対象
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)High
対象
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)High
対象
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 stateLow
対象
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_SHRINKMedium
対象
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

ColumnMeaningWhat to Check
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

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)

  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.

Diagnostic Steps

  1. 1

    Check free space per file

    Read-only

    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

    Read-only

    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`

    Read-only

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

  4. 4

    Record the fragmentation percentage before shrinking

    Low

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

  5. 5

    Check the autogrowth setting

    Read-only

    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

    Read-only

    If `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-only

    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

    Medium

    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

    Low

    Shrink 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`

    High

    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

    Medium

    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

    Medium

    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

    Medium

    Designing 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

    High

    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`

    High

    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

    High

    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.

!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

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

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.

Related Knowledge

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

← Back to Knowledge Base