DBCC SHRINKFILE (Transact-SQL)

壓縮目前資料庫之指定資料或記錄檔的大小,或藉由將資料從指定檔案移到同一檔案群組中的其他檔案的方式來清除檔案 (讓檔案可以從資料庫中移除)。 檔案可以壓縮成小於當初建立時所指定的大小。 這會將檔案大小下限重設為新值。

主題連結圖示 Transact-SQL 語法慣例

語法

DBCC SHRINKFILE 
(
    { file_name | file_id } 
    { [ , EMPTYFILE ] 
    | [ [ , target_size ] [ , { NOTRUNCATE | TRUNCATEONLY } ] ]
    }
)
[ WITH NO_INFOMSGS ]

引數

  • file_name
    這是要壓縮之檔案的邏輯名稱。

  • file_id
    這是要壓縮之檔案的識別碼 (ID)。 若要取得檔案識別碼,請使用 FILE_IDEX 系統函數或在目前的資料庫中查詢 sys.database_files 目錄檢視。

  • target_size
    這是檔案的大小 (MB),以整數表示。 若未指定,DBCC SHRINKFILE 會將大小縮減成預設檔案大小。 預設的大小是在建立檔案時所指定的大小。

    [!附註]

    您可以使用 DBCC SHRINKFILE target_size 縮減空白檔案的預設大小。 例如,如果建立 5 MB 的檔案,然後再將檔案縮減為 3 MB 且檔案仍維持空白,則預設的檔案大小會設定為 3 MB。 這僅適用於從未包含過資料的空白檔案。

    FILESTREAM 檔案群組容器不支援此選項。

    如果指定了 target_size,DBCC SHRINKFILE 會嘗試將檔案壓縮成指定的大小。 檔案將釋出之部分所用的頁面,重新放置到檔案保留部分的可用空間中。 例如,如果有 10 MB 的資料檔,將 target_size 設為 8 的 DBCC SHRINKFILE 作業會使檔案最後 2 MB 所用的所有頁面,都重新配置到檔案前 8 MB 的任何未配置頁面中。 DBCC SHRINKFILE 不會將檔案壓縮到小於將資料儲存在檔案中所需要的大小。 例如,如果使用了 10 MB 資料檔中的 7 MB,將 target_size 設為 6 的 DBCC SHRINKFILE 陳述式,只會將檔案壓縮成 7 MB,而不是 6 MB。

  • EMPTYFILE
    將指定檔案中的所有資料移轉到相同檔案群組的其他檔案中。 因為 Database Engine 不再允許將資料放入空白檔案,所以可以使用 ALTER DATABASE 陳述式移除檔案。

    對於 FILESTREAM 檔案群組容器來說,在 FILESTREAM 記憶體回收行程已執行並刪除所有由 EMPTYFILE 複製至其他容器且已不需要的檔案群組容器檔案之前,檔案將無法使用 ALTER DATABASE 移除。 如需詳細資訊,請參閱<sp_filestream_force_garbage_collection (Transact-SQL)

    [!附註]

    如需有關移除 FILESTREAM 容器的詳細資訊,請參閱<ALTER DATABASE 檔案及檔案群組選項 (Transact-SQL)>中對應的章節。

  • NOTRUNCATE
    在有指定或未指定 target_percent 的情況下,將配置的頁面從資料檔結尾移到檔案前面未配置的頁面。 檔案結尾的可用空間並不會還給作業系統,檔案的實際大小也不會改變。 因此,當指定了 NOTRUNCATE 時,檔案不會呈現壓縮狀態。

    NOTRUNCATE 只適用於資料檔。 記錄檔不受影響。

    FILESTREAM 檔案群組容器不支援此選項。

  • TRUNCATEONLY
    將檔案結尾的所有可用空間釋放給作業系統,但是不會在檔案內移動任何頁面。 資料檔只會壓縮為最後配置的範圍。

    如果在使用 TRUNCATEONLY 時指定 target_size 選項,會忽略此選項。

    TRUNCATEONLY 選項不會移動記錄檔中的資訊,但會從記錄檔結尾移除非使用中的 VLF。 FILESTREAM 檔案群組容器不支援此選項。

  • WITH NO_INFOMSGS
    抑制所有參考訊息。

結果集

下表描述結果集中的資料行。

資料行名稱

描述

DbId

Database Engine 試圖壓縮之檔案的資料庫識別碼。

FileId

Database Engine 試圖壓縮之檔案的檔案識別碼。

CurrentSize

檔案目前所佔的 8 KB 頁數。

MinimumSize

檔案所能佔用的 8 KB 頁數最小值。 這對應於檔案的大小下限或最初建立的大小。

UsedPages

檔案目前所用的 8 KB 頁數。

EstimatedPages

Database Engine 估計檔案可以壓縮成 8 KB 頁面的數目。

備註

DBCC SHRINKFILE 適用於目前資料庫中的檔案。 如需有關如何變更目前資料庫的詳細資訊,請參閱<USE (Transact-SQL)>。

在這個處理序中,隨時可以停止 DBCC SHRINKFILE 作業,任何已完成的工作都會保留下來。

當 DBCC SHRINKFILE 作業失敗時,會引發錯誤。

壓縮的資料庫不必是單一使用者模式;在檔案壓縮之後,其他使用者也可以在這個資料庫中工作。 您不需要在單一使用者模式中執行 SQL Server 執行個體,來壓縮系統資料庫。

壓縮記錄檔

對於記錄檔,Database Engine 會利用 target_size 來計算整份記錄的目標大小;因此,target_size 是壓縮作業之後記錄中可用的空間量。 之後,便會將整份記錄的目標大小轉換成每個記錄檔的目標大小。 DBCC SHRINKFILE 會試圖將每個實體記錄檔立即壓縮成目標大小。 不過,如果邏輯記錄有任何部分是在超出目標大小的虛擬記錄中,Database Engine 會釋出盡可能多的空間,然後發出一則參考用訊息。 這個訊息描述將邏輯記錄移出檔案結尾的虛擬記錄,需要哪些動作。 執行這些動作之後,就可以利用 DBCC SHRINKFILE 來釋出其餘空間。

由於記錄檔只能壓縮成虛擬記錄檔界限,因此,可能無法將記錄檔壓縮成小於虛擬記錄檔的大小,即使它不在使用中,也是如此。 建立或擴充記錄檔時,Database Engine 會動態選擇虛擬記錄檔的大小。

最佳作法

當您計畫壓縮檔案時,請考量下列資訊:

  • 壓縮作業在截斷資料表或卸除資料表等產生大量未用空間的作業之後最有效。

  • 大部分資料庫都需要一些可用空間來執行每天的例行作業。 如果您反覆壓縮資料庫,發現資料庫再次增長,就表示例行作業需要被壓縮的空間。 在這些情況之下,反覆壓縮資料庫是一項會造成浪費的作業。

  • 壓縮作業不會保留資料庫中索引的片段狀態,它通常會使片段增加到某個程度。 這就是不要反覆壓縮資料庫的另一個原因。

  • 依序將相同資料庫中的多個檔案壓縮,而不是同時壓縮。 爭用系統資料表可能會因為封鎖而導致延遲。

疑難排解

此章節描述如何診斷和更正在執行 DBCC SHRINKFILE 命令時可能發生的問題。

檔案無法壓縮

如果壓縮作業並未發生錯誤,但檔案並未呈現出大小變更的狀態,請執行下列其中一項作業來確認檔案具有足夠的可用空間可以移除:

  • 執行下列查詢。

    SELECT name ,size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS AvailableSpaceInMB
    FROM sys.database_files;
    
  • 執行 DBCC SQLPERF 命令傳回交易記錄中所使用的空間。

如果可用的空間不足,壓縮作業無法更進一步地縮減檔案大小。

一般而言,呈現未壓縮狀態的都是記錄檔。 這通常是因為記錄檔未遭截斷而造成。 您可以藉由下列方式截斷記錄檔:將資料庫復原模式設定為 SIMPLE,或者先備份記錄檔,然後再執行 DBCC SHRINKFILE 作業一次。

壓縮作業遭到封鎖

壓縮作業可以由在資料列版本設定隔離等級之下執行的交易進行封鎖。 例如,當 DBCC SHRINK DATABASE 作業執行時,如果以資料列版本設定為基礎的隔離等級之下正在進行大量刪除作業,則壓縮作業將會等到刪除作業完成之後,才會開始壓縮檔案。 當這種情況發生時,DBCC SHRINKFILE 和 DBCC SHRINKDATABASE 作業在第一個小時裡,會每五分鐘列印一次參考用訊息 (SHRINKDATABASE 是 5202,SHRINKFILE 是 5203) 到 SQL Server 錯誤記錄檔中,之後則每小時列印一次。 例如,如果錯誤記錄檔包含下列錯誤訊息,就會發生下列錯誤:

DBCC SHRINKFILE for file ID 1 is waiting for the snapshot 
transaction with timestamp 15 and other snapshot transactions linked to 
timestamp 15 or with timestamps older than 109 to finish.

這表示壓縮作業是由時間戳記在 109 (壓縮作業所完成的最後一項交易) 之前的快照集交易所封鎖。 也表示 sys.dm_tran_active_snapshot_database_transactions 動態管理檢視中的 transaction_sequence_numfirst_snapshot_sequence_num 資料行包含 15 的值。 如果檢視表中的 transaction_sequence_numfirst_snapshot_sequence_num 資料行所包含的數字小於壓縮作業所完成的最後一項交易 (109),壓縮作業將會等到這些交易完成。

若要解決這個問題,可以執行下列其中一項工作:

  • 結束正在封鎖壓縮作業的交易。

  • 結束壓縮作業。 如果結束壓縮作業,則所有已完成的工作都會保留。

  • 不執行任何動作,並允許壓縮作業等到封鎖交易完成。

權限

需要系統管理員 (sysadmin) 固定伺服器角色或 db_owner 固定資料庫角色中的成員資格。

範例

A.將資料檔壓縮為指定的目標大小

下列範例會將 UserDB 使用者資料庫中名為 DataFile1 之資料檔大小壓縮成 7 MB。

USE UserDB;
GO
DBCC SHRINKFILE (DataFile1, 7);
GO

B.將記錄檔壓縮為指定的目標大小

下列範例會將 AdventureWorks 資料庫中的記錄檔壓縮成 1 MB。 若要讓 DBCC SHRINKFILE 命令可以壓縮檔案,必須先將資料庫復原模式設定為 SIMPLE 以截斷檔案。

USE AdventureWorks2012;
GO
-- Truncate the log by changing the database recovery model to SIMPLE.
ALTER DATABASE AdventureWorks2012
SET RECOVERY SIMPLE;
GO
-- Shrink the truncated log file to 1 MB.
DBCC SHRINKFILE (AdventureWorks2012_Log, 1);
GO
-- Reset the database recovery model.
ALTER DATABASE AdventureWorks2012
SET RECOVERY FULL;
GO

C.截斷資料檔

下列範例會截斷 AdventureWorks 資料庫中的主要資料檔, 並查詢 sys.database_files 目錄檢視以取得資料檔的 file_id。

USE AdventureWorks2012;
GO
SELECT file_id, name
FROM sys.database_files;
GO
DBCC SHRINKFILE (1, TRUNCATEONLY);

D.清除檔案

下列範例示範清除檔案,使其能從資料庫中移除的程序。 在此範例中會先建立一個資料檔,然後假設該檔案包含資料。

USE AdventureWorks2012;
GO
-- Create a data file and assume it contains data.
ALTER DATABASE AdventureWorks2012 
ADD FILE (
    NAME = Test1data,
    FILENAME = 'C:\t1data.ndf',
    SIZE = 5MB
    );
GO
-- Empty the data file.
DBCC SHRINKFILE (Test1data, EMPTYFILE);
GO
-- Remove the data file from the database.
ALTER DATABASE AdventureWorks2012
REMOVE FILE Test1data;
GO

請參閱

參考

ALTER DATABASE (Transact-SQL)

DBCC (Transact-SQL)

DBCC SHRINKDATABASE (Transact-SQL)

FILE_ID (Transact-SQL)

sys.database_files (Transact-SQL)

概念

壓縮檔案