在 Azure SQL Database 中管理資料庫的檔案空間

適用于:Azure SQL資料庫

本文說明 Azure SQL Database 中不同類型的資料庫儲存空間,及需要明確管理檔案空間配置時,可採取的步驟。

注意

本文「不」適用於 Azure SQL Database 受控執行個體。

概觀

在 Azure SQL Database 的某些工作負載模式中,資料庫的基礎資料檔案配置可能會逐漸大於已使用資料頁數。 當使用的空間增加,隨後卻將資料刪除時,就會發生這種狀況。 原因是因為在資料刪除後,並不會自動回收已配置的檔案空間。

在下列情況中,可能需要監視檔案空間使用量和壓縮資料檔案:

  • 當配置給檔案資料庫的檔案空間達到集區大小上限時,允許彈性集區中的資料成長。
  • 允許減少單一資料庫或彈性集區的大小上限。
  • 允許將單一資料庫或彈性集區變更為大小上限較低的不同服務層級或效能層級。

注意

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

監視檔案空間使用量

下列 API 顯示的多數儲存體空間計量,只會測量已使用的資料頁面大小:

  • Azure Resource Manager 型計量 API 包括 PowerShell get-metrics

不過,下列 API 也會測量配置給資料庫和彈性集區的空間大小:

了解資料庫的儲存體空間類型

要管理資料庫的檔案空間,務必要了解下列儲存體空間數量。

資料庫數量 定義 註解
已使用的資料空間 用來儲存資料庫資料的空間量。 一般而言,使用的空間會在插入 (刪除) 時增加 (減少)。 在某些情況下,根據作業與任何分割中涉及的資料量和模式而定,使用的空間並不會隨插入或刪除而變更。 例如,從每個資料頁刪除一個資料列,不見得會減少使用的空間。
已配置的資料空間 可用以儲存資料庫資料的格式化檔案空間量。 配置的空間量會自動成長,但絕不會在刪除後減少。 此行為可確保未來能更快地插入,因為不需要重新格式化空間。
已配置但未使用的資料空間 已配置的資料空間量與已使用的資料空間之間的差異。 此數量代表可藉由壓縮資料檔案而回收的可用空間量上限。
資料大小上限 可用來儲存資料庫資料的空間量上限。 配置的資料空間量不得成長超過資料大小上限。

下圖說明資料庫的不同儲存體空間類型之間的關聯性。

儲存體空間類型和關聯性

查詢資料庫來取得儲存體空間資訊

下列查詢可用來判斷單一資料庫的儲存體空間數量。

使用的資料庫資料空間

修改下列查詢,以傳回資料庫已使用的資料空間量。 查詢結果以 MB 為單位。

-- Connect to master
-- Database data space used in MB
SELECT TOP 1 storage_in_megabytes AS DatabaseDataSpaceUsedInMB
FROM sys.resource_stats
WHERE database_name = 'db1'
ORDER BY end_time DESC;

配置的資料庫資料空間與已配置但未使用的空間

使用下列查詢,以傳回已配置的資料庫資料空間量與已配置但未使用的空間量。 查詢結果以 MB 為單位。

-- Connect to database
-- Database data space allocated in MB and database data space allocated unused in MB
SELECT SUM(size/128.0) AS DatabaseDataSpaceAllocatedInMB,
SUM(size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0) AS DatabaseDataSpaceAllocatedUnusedInMB
FROM sys.database_files
GROUP BY type_desc
HAVING type_desc = 'ROWS';

資料庫資料大小上限

修改下列查詢,以傳回資料庫資料大小上限。 查詢結果以位元組為單位。

-- Connect to database
-- Database data max size in bytes
SELECT DATABASEPROPERTYEX('db1', 'MaxSizeInBytes') AS DatabaseDataMaxSizeInBytes;

了解彈性集區的儲存體空間類型

要管理彈性集區的檔案空間,務必要了解下列儲存體空間數量。

彈性集區數量 定義 註解
已使用的資料空間 彈性集區中的所有資料庫所使用的資料空間總和。
已配置的資料空間 彈性集區中的所有資料庫所配置的資料空間總和。
已配置但未使用的資料空間 已配置的資料空間量與彈性集區中的所有資料庫已使用的資料空間之間的差異。 此數量代表已為彈性集區配置、且可藉由壓縮資料檔案而回收的空間量上限。
資料大小上限 彈性集區可用於其所有資料庫的資料空間量上限。 為彈性集區配置的空間不應超過彈性集區大小上限。 如果發生此狀況,則可藉由壓縮資料庫資料檔案來回收已配置但未使用的空間。

注意

「彈性集區已達儲存體限制」錯誤訊息表示,已為資料庫物件配置符合彈性集區儲存體限制的足夠空間,但資料空間配置可能有未使用的空間。 請考慮增加彈性集區的儲存體限制,或使用下方的〈回收未使用的配置空間〉一節作為短期解決方案,釋出資料空間。 您也應留意壓縮資料庫檔案可能對效能造成負面的影響,請參閱下方的壓縮後的索引維修一節。

查詢彈性集區,以取得儲存體空間資訊

下列查詢可用來判斷彈性集區的儲存體空間數量。

使用的彈性集區資料空間

修改下列查詢,以傳回已使用的彈性集區資料空間量。 查詢結果以 MB 為單位。

-- Connect to master
-- Elastic pool data space used in MB  
SELECT TOP 1 avg_storage_percent / 100.0 * elastic_pool_storage_limit_mb AS ElasticPoolDataSpaceUsedInMB
FROM sys.elastic_pool_resource_stats
WHERE elastic_pool_name = 'ep1'
ORDER BY end_time DESC;

配置的彈性集區資料空間與已配置但未使用的空間

修改下列範例,並傳回資料表,列出彈性集區各資料庫配置的空間和未使用的配置空間。 此資料表會根據資料庫已配置但未使用的空間量,從最大至最小來排序資料庫。 查詢結果以 MB 為單位。

以查詢判斷為集區中的每個資料庫配置的空間所產生的結果,可在加總後用來判斷為彈性集區配置的總空間。 配置的彈性集區空間不應超過彈性集區大小上限。

重要

Azure SQL Database 仍然支援 PowerShell Azure Resource Manager 模組,但所有未來的開發都是針對 Az.Sql 模組。 AzureRM 模組在至少 2020 年 12 月之前都還會持續收到 Bug 修正。 Az 模組和 AzureRm 模組中命令的引數本質上完全相同。 如需其相容性的詳細資訊,請參閱新的 Azure PowerShell Az 模組簡介

PowerShell 指令碼需要 SQL Server PowerShell 模組 – 請參閱下載 PowerShell 模組以便安裝。

$resourceGroupName = "<resourceGroupName>"
$serverName = "<serverName>"
$poolName = "<poolName>"
$userName = "<userName>"
$password = "<password>"

# get list of databases in elastic pool
$databasesInPool = Get-AzSqlElasticPoolDatabase -ResourceGroupName $resourceGroupName `
    -ServerName $serverName -ElasticPoolName $poolName
$databaseStorageMetrics = @()

# for each database in the elastic pool, get space allocated in MB and space allocated unused in MB
foreach ($database in $databasesInPool) {
    $sqlCommand = "SELECT DB_NAME() as DatabaseName, `
    SUM(size/128.0) AS DatabaseDataSpaceAllocatedInMB, `
    SUM(size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0) AS DatabaseDataSpaceAllocatedUnusedInMB `
    FROM sys.database_files `
    GROUP BY type_desc `
    HAVING type_desc = 'ROWS'"
    $serverFqdn = "tcp:" + $serverName + ".database.windows.net,1433"
    $databaseStorageMetrics = $databaseStorageMetrics + 
        (Invoke-Sqlcmd -ServerInstance $serverFqdn -Database $database.DatabaseName `
            -Username $userName -Password $password -Query $sqlCommand)
}

# display databases in descending order of space allocated unused
Write-Output "`n" "ElasticPoolName: $poolName"
Write-Output $databaseStorageMetrics | Sort -Property DatabaseDataSpaceAllocatedUnusedInMB -Descending | Format-Table

下列螢幕擷取畫面是指令碼輸出的其中一個範例:

彈性集區的配置空間和未使用配置空間範例

彈性集區資料大小上限

修改下列 T-SQL 查詢,傳回上次記錄的彈性集區資料大小上限。 查詢結果以 MB 為單位。

-- Connect to master
-- Elastic pools max size in MB
SELECT TOP 1 elastic_pool_storage_limit_mb AS ElasticPoolMaxSizeInMB
FROM sys.elastic_pool_resource_stats
WHERE elastic_pool_name = 'ep1'
ORDER BY end_time DESC;

回收未使用的配置空間

重要

壓縮命令會在資料庫執行時影響其效能,如果可能,應該在低使用量期間執行。

壓縮資料檔案

由於可能會對資料庫效能造成影響,因此 Azure SQL Database 不會自動壓縮資料檔案。 但客戶可以隨時選擇自行壓縮資料檔案。 這不應是定期排程的作業,而是大幅減少資料檔案耗用空間的一次性事件。

提示

如果一般應用程式工作負載會讓檔案重新成長到相同的配置大小,即不建議您壓縮資料檔案。

在 Azure SQL Database 中,若要壓縮檔案,您可以使用 DBCC SHRINKDATABASEDBCC SHRINKFILE 命令:

  • DBCC SHRINKDATABASE 使用單一命令壓縮資料庫所有的資料和記錄檔。 此命令會一次壓縮一個資料檔案,所以較大的資料庫可能需要較長的時間。 此命令也可壓縮記錄檔,但這通常不是必要措施,因為 Azure SQL Database 會視需要自動壓縮記錄檔。
  • DBCC SHRINKFILE 命令支援更進階的案例:
    • 此命令可視需要壓縮個別檔案,而不是壓縮資料庫所有的檔案。
    • 每個 DBCC SHRINKFILE 命令都可以與其他 DBCC SHRINKFILE 命令平行執行,以同時壓縮多個檔案並減少壓縮的總時間,然而在壓縮期間同時執行這些命令,會造成較高的資源使用量,並可能會封鎖使用者查詢。
    • 如果檔案的結尾不包含資料,可以藉由指定引數 TRUNCATEONLY,以更快的速度減少配置的檔案大小。 這不需要在檔案中移動資料。
  • 如需這些壓縮命令的詳細資訊,請參閱 DBCC SHRINKDATABASEDBCC SHRINKFILE

下列範例必須在連線至目標使用者資料庫時執行,而不是在連線至 master 資料庫時執行。

若要使用 DBCC SHRINKDATABASE 壓縮指定資料庫所有的資料和記錄檔:

-- Shrink database data space allocated.
DBCC SHRINKDATABASE (N'database_name');

在 Azure SQL Database 中,資料庫可能會有一或多個資料檔案,隨著資料成長自動建立。 若要判斷資料庫的檔案配置,包括每個檔案已使用和配置的大小,請使用下列範例指令碼來查詢 sys.database_files 目錄檢視:

-- Review file properties, including file_id and name values to reference in shrink commands
SELECT file_id,
       name,
       CAST(FILEPROPERTY(name, 'SpaceUsed') AS bigint) * 8 / 1024. AS space_used_mb,
       CAST(size AS bigint) * 8 / 1024. AS space_allocated_mb,
       CAST(max_size AS bigint) * 8 / 1024. AS max_file_size_mb
FROM sys.database_files
WHERE type_desc IN ('ROWS','LOG');

您只能透過 DBCC SHRINKFILE 命令,執行單一檔案的壓縮,例如:

-- Shrink database data file named 'data_0` by removing all unused at the end of the file, if any.
DBCC SHRINKFILE ('data_0', TRUNCATEONLY);
GO

請留意壓縮資料庫檔案可能對效能造成負面的影響,請參閱下方的〈壓縮後的索引維修〉一節。

壓縮交易記錄檔

不同於資料檔案,Azure SQL Database 會自動壓縮交易記錄檔,以避免可能導致空間不足錯誤的過度空間使用量。 客戶通常不需要壓縮交易記錄檔。

在進階和業務關鍵服務層級中,如果交易記錄變大,可能會大為增加本機儲存體的耗用量,達到最大本機儲存體的限制。 如果本機儲存體耗用量接近限制,客戶可以選擇使用下列範例所示的 DBCC SHRINKFILE 命令,壓縮交易記錄。 命令完成後便會立即釋出本機儲存體,而不必等待定期自動壓縮作業。

下列範例應該在連接到目標使用者資料庫時執行,而不是 master 資料庫。

-- Shrink the database log file (always file_id 2), by removing all unused space at the end of the file, if any.
DBCC SHRINKFILE (2, TRUNCATEONLY);

自動壓縮

資料庫可啟用自動壓縮,做為手動壓縮資料檔案的替代方法。 不過,自動壓縮比起 DBCC SHRINKDATABASEDBCC SHRINKFILE 在回收檔案空間上可能較沒效率。

自動壓縮預設為停用,建議大部分資料庫保持此設定。 如果必須啟用自動壓縮,建議您在空間管理達成目標後停用此功能,而不是永久啟用。 如需詳細資訊,請參閱 AUTO_SHRINK 的考量

在特定的案例中,例如包含很多資料庫的彈性集區,其中使用的資料檔案空間會大幅的成長和減少,而導致集區接近大小上限,這時自動壓縮便會很實用。 這不是常見案例。

若要啟用自動壓縮,請在連線到資料庫 (而非 master 資料庫) 時執行下列命令。

-- Enable auto-shrink for the current database.
ALTER DATABASE CURRENT SET AUTO_SHRINK ON;

如需有關此命令的詳細資訊,請參閱 DATABASE SET 選項。

壓縮後的索引維修

完成資料檔案的壓縮作業後,索引可能會變得分散。 這會降低特定工作負載 (例如使用大型掃描的查詢) 的效能最佳化有效性。 如果壓縮作業完成後發生效能降低的情形,請考慮執行索引維修來重建索引。 請記得,索引重建需要資料庫具有可用空間,並可能導致已配置的空間增加,抵銷壓縮的效果。

如需索引維修的詳細資訊,請參閱將索引維修最佳化以改善查詢效能並降低資源耗用量

壓縮大型資料庫

當資料庫配置的空間為數百 GB 以上時,壓縮可能需要很長的時間才能完成 (通常是以小時為單位),而多 TB 資料庫則可能需要數天才能完成。 您可以使用程序最佳化和最佳做法,讓程序更有效率,並降低對應用程式工作負載的影響。

擷取空間使用量基準

開始壓縮前,請執行下列空間使用量查詢,擷取各資料庫檔案目前已使用和配置的空間:

SELECT file_id,
       CAST(FILEPROPERTY(name, 'SpaceUsed') AS bigint) * 8 / 1024. AS space_used_mb,
       CAST(size AS bigint) * 8 / 1024. AS space_allocated_mb,
       CAST(max_size AS bigint) * 8 / 1024. AS max_size_mb
FROM sys.database_files
WHERE type_desc = 'ROWS';

完成壓縮之後,您可以再次執行此查詢,並將結果與初始基準進行比較。

截斷資料檔案

建議您先使用 TRUNCATEONLY 參數,執行各資料檔案的壓縮。 如此一來,如果檔案結尾有任何已配置但未使用的空間,即會立即移除,而不需移動任何資料。 下列範例命令會截斷 file_id 4 的資料檔案:

DBCC SHRINKFILE (4, TRUNCATEONLY);

各資料檔案執行此命令後,即可重新執行空間使用量查詢,查看已配置空間是否有任何減少。 您也可以在 Azure 入口網站中,檢視資料庫已配置的空間。

評估索引頁密度

如果截斷資料檔案未充分減少配置空間,即需壓縮資料檔案。 但請先判斷資料庫索引的頁面平均密度,這個步驟為選擇性但建議您採用。 如果以相同數量的資料而言,頁面密度高時,壓縮會更快完成,因為必須移動的頁面較少。 壓縮資料檔案前,如果部分索引的頁面密度較低,請考慮維修這些索引,增加頁面密度。 這也會讓壓縮大幅減少配置的儲存空間。

若要判斷資料庫中所有索引的頁面密度,請使用下列查詢。 頁面密度會在 avg_page_space_used_in_percent 資料行中報告。

SELECT OBJECT_SCHEMA_NAME(ips.object_id) AS schema_name,
       OBJECT_NAME(ips.object_id) AS object_name,
       i.name AS index_name,
       i.type_desc AS index_type,
       ips.avg_page_space_used_in_percent,
       ips.avg_fragmentation_in_percent,
       ips.page_count,
       ips.alloc_unit_type_desc,
       ips.ghost_record_count
FROM sys.dm_db_index_physical_stats(DB_ID(), default, default, default, 'SAMPLED') AS ips
INNER JOIN sys.indexes AS i 
ON ips.object_id = i.object_id
   AND
   ips.index_id = i.index_id
ORDER BY page_count DESC;

壓縮資料檔案前,如果索引包含高頁面計數,但頁面密度低於 60-70%,請考慮重建或重新組織這些索引。

注意

如果是較大的資料庫,判斷頁面密度的查詢可能需要較長時間 (數小時) 才能完成。 此外,重建或重新組織大型索引也需要大量的時間和資源使用量。 在花費額外時間增加頁面密度,與縮短壓縮時間並達成較高的空間節省之間需各有取捨。

以下是重建索引和增加索引頁面密度的範例命令:

ALTER INDEX [index_name] ON [schema_name].[table_name] REBUILD WITH (FILLFACTOR = 100, MAXDOP = 8, ONLINE = ON (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 5 MINUTES, ABORT_AFTER_WAIT = NONE)), RESUMABLE = ON);

此命令會初始化線上且可繼續的索引重建。 如此一來,並行工作負載可在重建執行的同時繼續使用資料表,且您可在重建因任何理由中斷時將其繼續。 但比起會封鎖資料表存取的離線重建,此類重建的速度較慢。 重建時,如果沒有其他工作負載需要存取資料表,請將 ONLINERESUMABLE 選項設為 OFF,並移除 WAIT_AT_LOW_PRIORITY 子句。

如果有多個包含低頁面密度的索引,您可以在多個資料庫工作階段平行重建這些索引,加速處理程序。 但請確定這麼做不會接近資料庫資源限制,並為可能正在執行的應用程式工作負載,保留足夠的資源空餘空間。 在 Azure 入口網站或使用 sys.dm_db_resource_stats 檢視來監視資源耗用量 (CPU、資料 IO、記錄 IO),並只在這些維度的個別資源使用率大幅低於 100% 時,才啟動額外的平行重建。 如果 CPU、資料 IO 或記錄 IO 使用率為 100%,您可以擴大資料庫,使用更多 CPU 核心並增加 IO 輸送量。 這可能會啟用額外的平行重建,加快完成處理程序。

若要深入了解索引維修,請參閱將索引維修最佳化以改善查詢效能並降低資源耗用量

壓縮多個資料檔案

如先前所述,使用資料移動壓縮須花費長時間執行。 如果資料庫有多個資料檔案,您可以平行壓縮多個資料檔案,加速處理程序。 若要這麼做,請開啟多個資料庫工作階段,並以不同的 file_id 值在各工作階段使用 DBCC SHRINKFILE。 類似於先前重建索引,在開始每個新的平行壓縮命令前,請確定您有足夠的資源空餘空間 (CPU、資料 IO、記錄 IO)。

下列範例命令會壓縮 file_id 4 的資料檔案,並移動檔案中的頁面,嘗試減少配置大小至 52000 MB:

DBCC SHRINKFILE (4, 52000);

若要盡量減少檔案的配置空間,在執行陳述式時,請不要指定目標大小:

DBCC SHRINKFILE (4);

如果工作負載與壓縮同時執行,工作負載可能會在壓縮完成並截斷檔案前就開始使用壓縮所釋放出來的儲存空間。 這時,壓縮無法將配置空間減少至指定的目標。

您可以細分步驟,先壓縮各檔案來減輕這個問題。 所以在 DBCC SHRINKFILE 命令中,請設定小於檔案目前配置空間的目標,如基準空間使用量查詢的結果中所示。 例如,如果 file_id 4 的檔案配置空間為 200,000 MB,而您想要將其壓縮為 100,000 MB,可先將目標設為 170,000 MB:

DBCC SHRINKFILE (4, 170000);

完成後,此命令會截斷檔案,並減少配置大小至 170,000 MB。 接著您可以重複此命令,先將目標設為 140,000 MB,然後是 110,000 MB,以此類推,直到檔案壓縮至所需大小。 如果命令完成,但未截斷檔案,請再細分步驟,改為每次減少 15,000 MB 而非 30,000 MB。

若要監視所有同時執行的壓縮工作階段的壓縮程序,您可以使用下列查詢:

SELECT command,
       percent_complete,
       status,
       wait_resource,
       session_id,
       wait_type,
       blocking_session_id,
       cpu_time,
       reads,
       CAST(((DATEDIFF(s,start_time, GETDATE()))/3600) AS varchar) + ' hour(s), '
                     + CAST((DATEDIFF(s,start_time, GETDATE())%3600)/60 AS varchar) + 'min, '
                     + CAST((DATEDIFF(s,start_time, GETDATE())%60) AS varchar) + ' sec' AS running_time
FROM sys.dm_exec_requests AS r
LEFT JOIN sys.databases AS d
ON r.database_id = d.database_id
WHERE r.command IN ('DbccSpaceReclaim','DbccFilesCompact','DbccLOBCompact','DBCC');

注意

壓縮程序可能非線性,即使壓縮仍在進行中,percent_complete 資料行的值也可能長時間保持不變。

完成所有資料檔案的壓縮後,請重新執行空間使用量查詢 (或在 Azure 入口網站中查詢),判斷配置儲存體大小的減少結果。 如果不夠,且已使用空間與配置空間仍有很大的差異,您可以如先前所述重建索引。 這可能暫時進一步增加配置的空間,但在重建索引後再度壓縮資料檔案,應該會大幅減少配置的空間。

壓縮期間的暫時性錯誤

壓縮命令有時可能失敗,並出現各種錯誤,例如超時和鎖死。 一般而言,這些是暫時性錯誤,而且在相同的命令重複時不會再次發生。 如果壓縮因錯誤失敗,則會保留目前資料頁面的移動進度,並可重新執行相同的壓縮命令,繼續壓縮檔案。

下列範例指令碼顯示超時錯誤或鎖死錯誤發生時,如何使用重試迴圈執行壓縮,自動重試至所設上限次數。 此重試方法也適用壓縮時可能發生的許多其他錯誤。

DECLARE @RetryCount int = 3; -- adjust to configure desired number of retries
DECLARE @Delay char(12);

-- Retry loop
WHILE @RetryCount >= 0
BEGIN

BEGIN TRY

DBCC SHRINKFILE (1); -- adjust file_id and other shrink parameters

-- Exit retry loop on successful execution
SELECT @RetryCount = -1;

END TRY
BEGIN CATCH
    -- Retry for the declared number of times without raising an error if deadlocked or timed out waiting for a lock
    IF ERROR_NUMBER() IN (1205, 49516) AND @RetryCount > 0
    BEGIN
        SELECT @RetryCount -= 1;

        PRINT CONCAT('Retry at ', SYSUTCDATETIME());

        -- Wait for a random period of time between 1 and 10 seconds before retrying
        SELECT @Delay = '00:00:0' + CAST(CAST(1 + RAND() * 8.999 AS decimal(5,3)) AS varchar(5));
        WAITFOR DELAY @Delay;
    END
    ELSE -- Raise error and exit loop
    BEGIN
        SELECT @RetryCount = -1;
        THROW;
    END
END CATCH
END;

除了超時和鎖死,壓縮可能因為特定已知問題發生錯誤。

傳回的錯誤和緩解步驟,如下所示:

  • 錯誤號碼:49503,錯誤訊息:%.*ls:頁面 %d:%d 是非資料列保留版本存放區頁面,所以無法移動。頁面扣留原因:%ls。頁面扣留時間戳記:%I64d。

長時間執行的使用中交易,在保留版本存放區 (PVS) 中產生資料列版本時,就會發生這個錯誤。 壓縮無法移動包含這類資料列版本的頁面,所以這些頁面無法處理,並因這個錯誤失敗。

若要減輕問題,您必須等到這些長時間執行的交易完成。 或者,您可以識別並終止這些長時間執行的交易,但如果處理交易失敗不當,即可能影響應用程式。 尋找長時間執行交易的方式之一,是在執行壓縮命令的資料庫中,執行下列查詢:

-- Transactions sorted by duration
SELECT st.session_id,
       dt.database_transaction_begin_time,
       DATEDIFF(second, dt.database_transaction_begin_time, CURRENT_TIMESTAMP) AS transaction_duration_seconds,
       dt.database_transaction_log_bytes_used,
       dt.database_transaction_log_bytes_reserved,
       st.is_user_transaction,
       st.open_transaction_count,
       ib.event_type,
       ib.parameters,
       ib.event_info
FROM sys.dm_tran_database_transactions AS dt
INNER JOIN sys.dm_tran_session_transactions AS st
ON dt.transaction_id = st.transaction_id
OUTER APPLY sys.dm_exec_input_buffer(st.session_id, default) AS ib
WHERE dt.database_id = DB_ID()
ORDER BY transaction_duration_seconds DESC;

您可以使用 KILL 命令,並指定查詢結果中相關的 session_id 值,來終止交易:

KILL 4242; -- replace 4242 with the session_id value from query results

警告

終止交易可能對工作負載造成負面的影響。

終止或完成長時間執行的交易後,內部背景工作會在一段時間後,清除不再需要的資料列版本。 您可以使用下列查詢,監視 PVS 大小並量測清除進度。 在執行壓縮命令的資料庫中執行查詢:

SELECT pvss.persistent_version_store_size_kb / 1024. / 1024 AS persistent_version_store_size_gb,
       pvss.online_index_version_store_size_kb / 1024. / 1024 AS online_index_version_store_size_gb,
       pvss.current_aborted_transaction_count,
       pvss.aborted_version_cleaner_start_time,
       pvss.aborted_version_cleaner_end_time,
       dt.database_transaction_begin_time AS oldest_transaction_begin_time,
       asdt.session_id AS active_transaction_session_id,
       asdt.elapsed_time_seconds AS active_transaction_elapsed_time_seconds
FROM sys.dm_tran_persistent_version_store_stats AS pvss
LEFT JOIN sys.dm_tran_database_transactions AS dt
ON pvss.oldest_active_transaction_id = dt.transaction_id
   AND
   pvss.database_id = dt.database_id
LEFT JOIN sys.dm_tran_active_snapshot_database_transactions AS asdt
ON pvss.min_transaction_timestamp = asdt.transaction_sequence_num
   OR
   pvss.online_index_min_transaction_timestamp = asdt.transaction_sequence_num
WHERE pvss.database_id = DB_ID();

persistent_version_store_size_gb 資料行中回報的 PVS 大小相較於原始大小有了大幅減少後,重新執行壓縮便應該會成功。

  • 錯誤號碼:5223,錯誤訊息:%.*ls:空白頁面 %d:%d 無法解除配置。

如果有進行中的索引維修作業 (例如 ALTER INDEX),就可能發生此錯誤。 完成這些作業後,請重試壓縮命令。

如果此錯誤持續發生,可能必須重建相關的索引。 若要尋找要重建的索引,請在執行壓縮命令的相同資料庫中,執行下列查詢:

SELECT OBJECT_SCHEMA_NAME(pg.object_id) AS schema_name,
       OBJECT_NAME(pg.object_id) AS object_name,
       i.name AS index_name,
       p.partition_number
FROM sys.dm_db_page_info(DB_ID(), <file_id>, <page_id>, default) AS pg
INNER JOIN sys.indexes AS i
ON pg.object_id = i.object_id
   AND
   pg.index_id = i.index_id
INNER JOIN sys.partitions AS p
ON pg.partition_id = p.partition_id;

執行此查詢前,請使用錯誤訊息中的實際值,取代 <file_id><page_id> 預留位置。 例如,如果訊息是「空白頁 1:62669 無法解除配置」,則 <file_id>1,而 <page_id>62669

重建查詢所識別的索引,並重試壓縮命令。

  • 錯誤號碼:5201,錯誤訊息:DBCC SHRINKDATABASE:資料庫識別碼 %d 的檔案識別碼 %d 已跳過,因為檔案沒有足夠的可用空間可以回收。

此錯誤表示資料檔案無法進一步壓縮。 您可以移至下一個資料檔案。

下一步