共用方式為


DBCC SHRINKDATABASE (Transact-SQL)

適用於:SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體 Azure Synapse Analytics

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

注意

壓縮作業不應視為一般維修作業。 因定期商務作業成長的資料和記錄檔,不需要壓縮作業。

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

要壓縮的資料庫名稱或識別碼。 0 指定使用目前的資料庫。

target_percent

壓縮資料庫之後,資料庫檔案所要保留的可用空間百分比。

NOTRUNCATE

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

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

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

TRUNCATEONLY

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

具有 TRUNCATEONLY 選項的 DBCC SHRINKDATABASE 只會影響資料庫交易記錄檔。 若要截斷資料檔案,請改用 DBCC SHRINKFILE。 如需詳細資訊,請參閱 DBCC SHRINKFILE

WITH NO_INFOMSGS

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

壓縮作業的 WAIT_AT_LOW_PRIORITY

適用於:SQL Server 2022 (16.x) 和更新版本、Azure SQL Database、Azure SQL 受控執行個體

低優先順序等候功能可減少鎖定競爭。 如需詳細資訊,請參閱了解 DBCC SHRINKDATABASE 的並行問題

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

  • 您無法指定 ABORT_AFTER_WAIT 選項 NONE。

WAIT_AT_LOW_PRIORITY

WAIT_AT_LOW_PRIORITY 模式中執行壓縮命令時,需要結構描述穩定性 (Sch-S) 鎖定不遭到等候壓縮作業封鎖,直到壓縮作業停止等候並開始執行為止。 壓縮作業會在能夠取得結構描述修改鎖定 (Sch-M) 時執行鎖定。 如果 WAIT_AT_LOW_PRIORITY 模式中的新壓縮作業因長時間執行的查詢而無法取得鎖定,壓縮作業最終會在預設的 1 分鐘後逾時,並且結束而不會發生錯誤。

如果 WAIT_AT_LOW_PRIORITY 模式中的新壓縮作業因長時間執行的查詢而無法取得鎖定,壓縮作業最終會在預設的 1 分鐘後逾時,並且結束而不會發生錯誤。 如果壓縮作業由於同時查詢或保留 Sch-S 鎖定的查詢而無法取得 Sch-M 鎖定,就會發生這種情況。 發生逾時的時候,錯誤 49516 訊息會傳送至SQL Server 錯誤記錄檔,例如: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。 此時,您可以在 WAIT_AT_LOW_PRIORITY 模式中重試壓縮作業,知道不會對應用程式造成任何影響。

ABORT_AFTER_WAIT = [ SELF | BLOCKERS ]

  • SELF

    SELF 是預設選項。 結束目前正在執行的壓縮資料庫作業,但不採取任何動作。

  • BLOCKERS

    終止封鎖壓縮資料庫作業的所有使用者交易,讓作業可以繼續。 BLOCKERS 選項需要登入具有 ALTER ANY 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 選項。 如果您未如此指定,結果與您使用 TRUNCATEONLY 執行 DBCC SHRINKDATABASE 作業之後,使用 NOTRUNCATE 執行 DBCC SHRINKDATABASE 作業一樣。

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

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

使用 WAIT_AT_LOW_PRIORITY 指定時,壓縮作業的 Sch-M 鎖定要求會在執行命令 1 分鐘時,以低優先順序等候。 如果作業被阻擋的時間達到該持續時間,則會執行指定的 ABORT_AFTER_WAIT 動作。

在 Azure Synapse SQL 集區中,不建議執行壓縮命令,因為這是需要大量 I/O 的作業,而且可以將專用 SQL 集區(先前稱為 SQL DW)離線。 此外,執行此命令之後將會對您的資料倉儲快照集成本有所影響。

Azure SQL 超大規模資料庫的資料庫和檔案壓縮作業目前為預覽狀態。 如需有關預覽狀態的詳細資訊,請參閱 Azure SQL 超大規模資料庫的壓縮

已知問題

適用於:SQL Server、Azure SQL 資料庫、Azure SQL 受控執行個體、Azure Synapse Analytics 專用 SQL 集區

  • 目前,在壓縮的數據行存放區區段中使用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 量。

例如,如果您指定壓縮 mydbtarget_percent 為 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 環境。 當您的應用程式對資料庫資料表執行查詢時,這些查詢會取得和維護結構描述穩定性鎖定 (Sch-S) 直到查詢完成其作業為止。 嘗試在一般使用期間回收空間時,壓縮資料庫和壓縮檔案作業目前會在移動或刪除索引配置對應 (IAM) 頁面時,要求結構描述修改鎖定 (Sch-M),從而阻擋使用者查詢需要的 Sch-S 鎖定。 因此,長時間執行的查詢會阻擋壓縮作業,直到查詢完成為止。 這表示任何需要 Sch-S 鎖定的新查詢也會排入等候壓縮作業後方的佇列,而且也會遭到阻擋,進一步讓並行問題惡化。 這可能會影響應用程式查詢效能,也會導致難以完成必要的維護來壓縮資料庫檔案。 在 SQL Server 2022 (16.x) 中引進,壓縮在低優先順序等候 (WLP) 功能可藉由在 WAIT_AT_LOW_PRIORITY 模式中建立結構描述修改鎖定來解決此問題。 如需詳細資訊,請參閱壓縮作業的 WAIT_AT_LOW_PRIORITY

如需 Sch-S 和 Sch-M 鎖定的詳細資訊,請參閱交易鎖定和資料列版本設定指南

最佳做法

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

  • 壓縮作業在進行會產生未用空間的作業 (例如截斷資料表或卸除資料表作業) 之後最有效。
  • 大部分資料庫都需要一些可用空間來執行每天的例行作業。 如果您反覆壓縮資料庫檔案,發現資料庫再次增長,就表示例行作業需要可用空間。 在這些情況之下,反覆壓縮資料庫檔案是一項會造成浪費的作業。 資料庫檔案成長所需的自動成長事件會阻礙效能。
  • 壓縮作業不會保留資料庫中索引的片段狀態,它通常會使片段增加到某個程度。 這個結果就是不要反覆壓縮資料庫的另一個原因。
  • 除非有特定的需求,否則請不要將 AUTO_SHRINK 資料庫選項設定為 [開啟]。

疑難排解

壓縮作業可以由在資料列版本設定隔離等級之下執行的交易進行封鎖。 例如,當 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 的快照集交易會封鎖壓縮作業。 該交易是壓縮作業完成的最後一個交易。 其也表示 sys.dm_tran_active_snapshot_database_transactions (Transact-SQL) 動態管理檢視中的 transaction_sequence_numfirst_snapshot_sequence_num 資料行包含值 15。 檢視中的 transaction_sequence_numfirst_snapshot_sequence_num 資料行所包含數字可能小於壓縮作業所完成的最後一項交易 (109)。 如果是這樣,壓縮作業將會等到這些交易完成。

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

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

權限

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

範例

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

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

DBCC SHRINKDATABASE (UserDB, 10);
GO

B. 截斷資料庫

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

DBCC SHRINKDATABASE (AdventureWorks2022, TRUNCATEONLY);

C. 壓縮 Azure Synapse Analytics 資料庫

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

D. 使用 WAIT_AT_LOW_PRIORITY 壓縮資料庫

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

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