DBCC SHRINKDATABASE (Transact-SQL)

適用於:SQL ServerAzure SQL 資料庫Azure SQL 受控執行個體Azure Synapse AnalyticsMicrosoft Fabric 中的 SQL 資料庫

壓縮指定之資料庫中的資料和記錄檔大小。

不要把縮小手術當作定期維護。 由於定期、週期性商務作業而成長的資料和記錄檔不需要壓縮作業。

Transact-SQL 語法慣例

語法

SQL Server 的語法:

DBCC SHRINKDATABASE
( database_name | database_id | 0
     [ , target_percent ]
     [ , { NOTRUNCATE | TRUNCATEONLY } ]
)
[ WITH
    {
         [ WAIT_AT_LOW_PRIORITY
            [ (
                  <wait_at_low_priority_option_list>
             ) ]
         ]
         [ , NO_INFOMSGS ]
    }
]

<wait_at_low_priority_option_list> ::=
    <wait_at_low_priority_option>
    | <wait_at_low_priority_option_list>
      , <wait_at_low_priority_option>

<wait_at_low_priority_option> ::=
  ABORT_AFTER_WAIT = { SELF | BLOCKERS }

Azure Synapse Analytics 的語法:

DBCC SHRINKDATABASE
( database_name
     [ , target_percent ]
)
[ WITH NO_INFOMSGS ]

引數

{ database_name | database_id |0 }

資料庫的名稱或 ID 來縮減。 0 表示目前的資料庫。

目標百分比

縮減操作完成後,資料庫檔案中剩餘空間的百分比。

如果你指定 target_percentTRUNCATEONLY縮小操作可能不會釋放檔案末端的空閒空間。

NOTRUNCATE

將所指派頁面從檔案結尾移動到檔案前面未指派的頁面。 此動作會壓縮檔案內的資料。 target_percent 為選擇性。 Azure Synapse Analytics 不支援此選項。

檔案結尾的可用空間並不會還給作業系統,檔案的實際大小也不會改變。 因此,當您指定 NOTRUNCATE 時資料庫似乎不會壓縮。

NOTRUNCATE 僅適用於資料檔案。 NOTRUNCATE 不會影響記錄檔。

TRUNCATEONLY

將檔案結尾的所有可用空間釋放給作業系統。 不會在檔案內移動任何頁面。 資料檔案只會壓縮到最後一個指派的範圍。 Azure Synapse Analytics 不支援此選項。

如果你指定 target_percentTRUNCATEONLY縮小操作可能不會釋放檔案末端的空閒空間。

使用 NO_INFOMSGS

抑制所有嚴重性層級在 0 到 10 的參考用訊息。

壓縮作業的 WAIT_AT_LOW_PRIORITY

適用於:SQL Server 2022 (16.x) 及以後版本、Azure SQL Database、Azure SQL 受控執行個體、Microsoft Fabric 中的 SQL 資料庫

低優先權等待功能可減少縮減操作期間的鎖爭用。 如需詳細資訊,請參閱了解 DBCC SHRINKDATABASE 的並行問題

這項功能與在線上索引作業使用 WAIT_AT_LOW_PRIORITY 類似,但是有些差異。

  • 你無法指定 ABORT_AFTER_WAIT 選項 NONE
  • 你無法設定這個 MAX_DURATION 選項。 縮小操作的低優先鎖超時永遠是一分鐘。

WAIT_AT_LOW_PRIORITY

當在模式下執行WAIT_AT_LOW_PRIORITY縮小指令時,對於需要在索引配置映射(IAM)頁面上設定結構穩定性Sch-S()鎖定的查詢,縮減操作不會阻擋。 然而,縮水操作可透過 Sch-S IAM 頁面的鎖定來阻擋。 Shrink 只有在能取得所需的 IAM 頁面的結構修改鎖(schema modify lock (Sch-M)時才會繼續執行。

若在模式下的縮減操作 WAIT_AT_LOW_PRIORITY 無法取得此鎖,因為長期執行的查詢持有鎖, Sch-S 該縮減操作會以錯誤 49516 超時,例如: Msg 49516, Level 16, State 1, Line 134 Shrink timeout waiting to acquire schema modify lock in WLP mode to process IAM pageID 1:2865 on database ID 5

{ ABORT_AFTER_WAIT = [ 自我 |阻擋者 ] }

  • SELF

    SELF 是預設選項。 退出目前正在執行的縮減資料庫操作,且不採取任何進一步行動。

  • BLOCKERS

    終止阻擋壓縮檔案作業的所有使用者交易,讓作業可以繼續。 這個 BLOCKERS 選項需要登入時擁有 ALTER ANY CONNECTION OR KILL DATABASE CONNECTION 權限。

結果集

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

資料行名稱 描述
DbId 資料庫引擎嘗試壓縮之檔案的資料庫識別碼。
FileId 資料庫引擎試圖壓縮檔案的檔案識別碼。
CurrentSize 檔案目前所佔的 8 KB 頁數。
MinimumSize 檔案所能佔用的 8 KB 頁數最小值。 這個值對應於檔案大小下限或最初建立的大小。
UsedPages 檔案目前所用的 8 KB 頁數。
EstimatedPages 資料庫引擎估計檔案可以壓縮成 8 KB 頁面的數目。

注意

資料庫引擎 不會顯示未縮減檔案的列。

備註

若要壓縮特定資料庫的所有資料和記錄檔,請執行 DBCC SHRINKDATABASE 命令。 若要一次壓縮特定資料庫的一個資料或記錄檔,請執行 DBCC SHRINKFILE 命令。

若要檢視資料庫中目前的可用 (未配置) 空間量,請執行 sp_spaceused

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

資料庫的大小不得小於設定的資料庫大小下限。 最初建立資料庫時,您會指定大小下限。 或者,大小下限也可以是最後一次使用檔案大小變更作業明確設定的大小。 像是 DBCC SHRINKFILEALTER DATABASE 作業都是檔案大小變更作業的範例。

請考量資料庫最初建立大小為 10 MB 的大小。 然後,它成長到 100 MB。 即使已刪除資料庫中的所有資料,資料庫可縮減為最小程度便是 10 MB。

你可以在執行DBCC SHRINKDATABASE時指定NOTRUNCATE選項或選項。TRUNCATEONLY 如果你沒有指定任何一個選項,結果就像你先執行DBCC SHRINKDATABASE一個運算NOTRUNCATE,接DBCC SHRINKDATABASE著執行一個運算。TRUNCATEONLY

壓縮的資料庫不一定要處於單一使用者模式。 其他使用者可以在壓縮時使用資料庫,包括系統資料庫。

資料庫在備份時不能進行壓縮。 反過來說,當資料庫上正在進行壓縮作業時,也不能對其進行備份。

在 Azure Synapse 的 SQL 池中,避免執行 shrink 指令,因為這是 I/O 密集操作,可能會讓你專用的 SQL 池(前稱 SQL DW)離線。 這個指令也會影響你資料倉儲快照的成本。

已知問題

適用於:SQL Server、Azure SQL Database、Azure SQL 受控執行個體、Azure Synapse Analytics dedicated SQL pool

  • 在 SQL Server 2022(16.x)及更早版本中,壓縮欄位儲存段中 LOB 欄位類型(varbinary(max)varchar(max)和nvarchar(max))所使用的頁面無法透過 DBCC SHRINKDATABASEDBCC SHRINKFILE移動。 欲了解更多資訊,請參閱「列存儲索引的新功能」。

DBCC SHRINKDATABASE 的運作方式

DBCC SHRINKDATABASE 會以個別檔案為基礎來壓縮資料檔案,但會依照所有記錄檔都是在單一連續記錄集區的方式來壓縮記錄檔。 檔案必定從結尾處進行壓縮。

假設你有兩個日誌檔和一個資料庫中的 mydb資料檔,名為 。 每個資料檔案和記錄檔均為 10 MB,資料檔案則包含 6 MB 的資料。 資料庫引擎會計算每個檔案的目標大小。 這個值是檔案縮小後的目標大小。 當你用 target_percent 指定DBCC SHRINKDATABASE時,資料庫引擎 會計算目標大小為縮小後檔案中target_percent的空餘空間。

例如,如果您指定壓縮 mydb 為 25,則資料庫引擎會將這個資料檔案的目標大小計算為 8 MB (6 MB 資料加 2 MB 可用空間)。 因此,資料庫引擎會將資料檔案最後 2 MB 的任何資料移到資料檔案前 8 MB 中的任何可用空間,然後再壓縮檔案。

假設 mydb 的資料檔案包含 7 MB 的資料。 將 target_percent 指定為 30,可以將這個資料檔案壓縮到可用百分比 30。 不過,將 target_percent 指定為 40 並不會壓縮資料檔案,因為無法在資料檔案的目前總大小中建立足夠的可用空間。

您可以用另一個方式來考慮這個問題:40% 需要的可用空間 + 70% 完整資料檔案 (10 MB 中的 7 MB) 會超出 100%。 大於 30 的任何 target_percent 都不會壓縮資料檔案。 它不會壓縮,因為您想要的可用百分比加上目前資料檔案所佔百分比已超過 100%。

針對記錄檔,資料庫引擎會使用 target_percent 來計算整份記錄的目標大小。 這就是為什麼 target_percent 是壓縮作業之後的記錄檔可用空間量。 之後,便會將整份記錄的目標大小轉換成每個記錄檔的目標大小。

DBCC SHRINKDATABASE 會試圖將每個實體記錄檔立即壓縮成目標大小。 如果邏輯日誌中沒有任何部分停留在虛擬日誌中超過該日誌檔案的目標大小,則 DBCC SHRINKDATABASE 成功截斷該檔案並結束且不會發出任何訊息。 不過,如果邏輯記錄有任何部分會在超出目標大小時留在虛擬記錄中,資料庫引擎會盡可能釋出空間,然後發出一則參考用訊息。 訊息描述了將邏輯日誌從檔案末尾虛擬日誌中移出的動作。 執行完動作後,使用 DBCC SHRINKDATABASE 來釋放剩餘空間。

你只能將日誌檔案縮小到虛擬日誌檔案邊界。 這就是為什麼無法將日誌檔案縮小到比虛擬日誌檔案大小還小的原因。 資料庫引擎 在建立或擴充日誌檔案時會動態選擇虛擬日誌檔案的大小。

了解 DBCC SHRINKDATABASE 的並行問題

縮減資料庫與縮減檔案指令可能導致並行性問題,尤其是在進行如重建索引等主動維護時,或在繁忙的 OLTP 環境中。

例如,使用者查詢可能會在索引配置圖(IAM)頁面取得結構穩定性Sch-S()鎖定,並持續保持直到完成。 在一般使用時嘗試回收空間時,縮小資料庫與縮減檔案操作在移動或刪除 IAM 頁面時需使用結構修改Sch-M鎖,阻擋 Sch-S 使用者查詢所需的鎖。 因此,長時間執行的查詢可能會阻擋縮縮操作。 這種行為也意味著任何需要在 IAM 頁面上鎖定 Sch-S 的新查詢,都可能排在縮小操作後面,進一步加劇並行性問題。

在 SQL Server 2022(16.x)中引入的低優先權等待功能,透過在 IAM 頁面WAIT_AT_LOW_PRIORITY上執行結構修改鎖定來解決此問題。 如需詳細資訊,請參閱壓縮作業的 WAIT_AT_LOW_PRIORITY

欲了解更多關於 Sch-S 鎖的資訊, Sch-M 請參閱 交易鎖定與列版本控制指南

最佳做法

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

  • 壓縮作業在進行會產生未用空間的作業 (例如截斷資料表或卸除資料表作業) 之後最有效。

  • 大多數資料庫需要一些空間來進行日常運作。 如果你反覆縮小資料庫檔案,發現資料庫大小又變大,這表示一般操作需要空閒空間。 在這些情況下,反覆縮小資料庫檔案反而適得其反。 檔案在縮小後分配新空間所需的檔案成長,可能會阻礙效能。

  • 縮減操作無法保留資料庫中索引的碎片狀態,且可能增加索引碎片,進而降低使用大型掃描查詢時的讀取 I/O 吞吐量。

  • 除非您有特定需求,否則請勿將 AUTO_SHRINK 資料庫選項設定為 ON

  • 如果你需要縮小大型資料庫的資料檔案,可以考慮使用 ShrinkDriver PowerShell 腳本。 該腳本自動化並簡化了縮減過程,將其轉化為單一、可觀察且可重複的操作。 腳本會平行縮減多個檔案,中斷時重試,並在執行時輸出詳細狀態報告。

疑難排解

以資料列版本設定為基礎的隔離等級下執行的交易可以封鎖壓縮作業。 例如,當你在一個基於資料列的隔離層級下執行大型刪除操作時執行 DBCC SHRINKDATABASE 。 在這種情況下,縮減操作會等待刪除操作完成後才會縮減檔案。 當壓縮作業等候時,DBCC SHRINKFILEDBCC SHRINKDATABASE 作業會列印參考訊息 (針對 SHRINKDATABASE 為 5202,針對 SHRINKFILE 為 5203)。 這個訊息在前一小時每五分鐘印到SQL Server錯誤日誌,之後每小時一次。 例如,如果錯誤記錄檔包含下列的錯誤訊息:

DBCC SHRINKDATABASE for database ID 9 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 的快照交易會阻擋縮小操作。 該交易是壓縮作業完成的最後一個交易。 同時也表示transaction_sequence_numsys.dm_tran_active_snapshot_database_transactions動態管理檢視中 or first_snapshot_sequence_num 欄位的值為 15。 檢視中的 transaction_sequence_numfirst_snapshot_sequence_num 資料行所包含數字可能小於壓縮作業所完成的最後一項交易 (109)。 如果是,壓縮作業會等候這些交易完成。

要解決這個問題,你可以做以下其中之一:

  • 結束正在封鎖壓縮作業的交易。
  • 結束壓縮作業。 所有已完成的工作都會保留。
  • 不執行任何動作,並允許壓縮作業等到封鎖交易完成。

權限

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

範例

本文中的程式代碼範例會使用 AdventureWorks2025AdventureWorksDW2025 範例資料庫,您可以從 Microsoft SQL Server 範例和社群專案 首頁下載。

A。 壓縮資料庫並指定可用空間百分比

下列範例會縮小 UserDB 使用者資料庫中的資料和記錄檔大小,使資料庫中能有 10% 的可用空間。

DBCC SHRINKDATABASE (UserDB, 10);
GO

B. 截斷資料庫

下列範例會將 AdventureWorks2025 範例資料庫中資料檔案和記錄檔壓縮為最後指派的範圍。

DBCC SHRINKDATABASE (AdventureWorks2025, TRUNCATEONLY);

C. 壓縮 Azure Synapse Analytics 資料庫

DBCC SHRINKDATABASE (database_A);
DBCC SHRINKDATABASE (database_B, 10);

D. 縮小資料庫 WAIT_AT_LOW_PRIORITY

下列範例會嘗試縮小 AdventureWorks2025 資料庫中的資料和記錄檔大小,使資料庫中能有 20% 的可用空間。 如果鎖定無法在一分鐘內取得,壓縮作業就會中止。

DBCC SHRINKDATABASE ([AdventureWorks2025], 20) WITH WAIT_AT_LOW_PRIORITY (ABORT_AFTER_WAIT = SELF);