承接上篇「分區函數、分區配置與建立分區表」,本文深入探討分區的進階運維:滑動視窗機制、分區切割/合併、索引維護、統計資料更新,以及查詢效能調校關鍵點,協助 DBA 在生產環境穩定運作大型分區表。
滑動視窗維持固定數量的分區(如保留 13 個月),每月將最舊分區 SWITCH OUT 至歸檔表,最新分區 SWITCH IN 新資料,再調整分區函數範圍。此操作為 中繼資料層級,幾乎零停機、零資料移動。
-- 參數
DECLARE @ArchiveTable dbo.Sales_Archive; -- 結構相同的歸檔表
DECLARE @PartitionNumber INT = 1; -- 最舊分區編號
DECLARE @BoundaryValue DATE = '2023-01-01'; -- 要移除的邊界值
BEGIN TRAN;
-- 1. 建立暫存表承接最舊分區資料(結構、索引、檢查條件須與分區表完全一致)
CREATE TABLE dbo.Sales_SwitchOut (
SaleID BIGINT NOT NULL,
SaleDate DATE NOT NULL,
Amount MONEY NOT NULL,
-- 其他欄位...
CONSTRAINT CK_Sales_SwitchOut_Date CHECK (SaleDate < @BoundaryValue)
) ON [PRIMARY]; -- 放在非分區檔案群組
-- 2. SWITCH OUT:中繼資料操作,瞬間完成
ALTER TABLE dbo.Sales SWITCH PARTITION @PartitionNumber TO dbo.Sales_SwitchOut;
-- 3. 將資料移入歸檔表(可選:壓縮、移至冷儲存)
INSERT INTO dbo.Sales_Archive SELECT * FROM dbo.Sales_SwitchOut;
DROP TABLE dbo.Sales_SwitchOut;
-- 4. 移除分區函數最舊邊界值
ALTER PARTITION FUNCTION pf_Monthly() MERGE RANGE (@BoundaryValue);
-- 5. 新增下個月份邊界值(擴展分區配置至新檔案群組)
ALTER PARTITION SCHEME ps_Monthly NEXT USED [FG_202402];
ALTER PARTITION FUNCTION pf_Monthly() SPLIT RANGE ('2024-02-01');
COMMIT TRAN;
TRY...CATCH、記錄表、Email 通知。-- 先指定新分區使用的檔案群組
ALTER PARTITION SCHEME ps_Monthly NEXT USED [FG_202403];
-- 切割:在 2024-03-01 建立新邊界,原分區一分為二
ALTER PARTITION FUNCTION pf_Monthly() SPLIT RANGE ('2024-03-01');
注意:SPLIT 會造成資料移動(將大於新邊界的列移至新分區),大分區執行時會產生大量記錄與鎖定。建議:
SWITCH OUT → SPLIT → SWITCH IN 模式。ALTER PARTITION FUNCTION pf_Monthly() MERGE RANGE ('2023-01-01');
MERGE 同樣涉及資料移動(將兩分區資料合併至單一分區),同樣需謹慎規劃時機。
-- 重建特定分區(線上、可指定壓縮、填充因子)
ALTER INDEX IX_Sales_Date ON dbo.Sales REBUILD PARTITION = 5
WITH (ONLINE = ON, DATA_COMPRESSION = PAGE, FILLFACTOR = 80);
-- 重組特定分區(較輕量,適合碎片率 10-30%)
ALTER INDEX IX_Sales_Date ON dbo.Sales REORGANIZE PARTITION = 5
WITH (LOB_COMPACTION = ON);
採用 sys.dm_db_index_physical_stats 掃描各分區碎片率,動態產生 REBUILD/REORGANIZE 指令,僅處理碎片超標分區,大幅縮短維護窗口。
SQL Server 2005 僅支援表級統計資料。大型分區表若資料分布不均,可能導致計畫選擇錯誤。對策:
AUTO_CREATE_STATISTICS、AUTO_UPDATE_STATISTICS。CREATE STATISTICS ST_Sales_Recent ON dbo.Sales (SaleDate)
WHERE SaleDate >= '2024-01-01'
WITH FULLSCAN;
查詢條件必須 直接參考分區欄位 且使用 SARGable 運算式,優化器才能消除不必要分區:
WHERE SaleDate >= '2024-01-01' AND SaleDate < '2024-02-01'WHERE YEAR(SaleDate) = 2024(函數導致掃描全表)WHERE SaleDate + 1 > '2024-01-01'(運算式導致掃描)OPTION (MAXDOP 8) 或資料庫範疇 MAXDOP 設定,避免單一查詢佔用所有 CPU。-- 分區資料列數、檔案群組、邊界值
SELECT p.partition_number, fg.name AS filegroup, prv.value AS boundary, p.rows
FROM sys.partitions p
JOIN sys.destination_data_spaces dds ON p.partition_number = dds.destination_id
JOIN sys.filegroups fg ON dds.data_space_id = fg.data_space_id
LEFT JOIN sys.partition_range_values prv ON prv.boundary_id = p.partition_number
WHERE p.object_id = OBJECT_ID('dbo.Sales');
-- 索引碎片率(分區級)
SELECT OBJECT_NAME(ips.object_id), ips.index_id, ips.partition_number,
ips.avg_fragmentation_in_percent, ips.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('dbo.Sales'), NULL, NULL, 'LIMITED') ips
WHERE ips.avg_fragmentation_in_percent > 10;
| 現象 | 可能原因 | 對策 |
|---|---|---|
| SWITCH 失敗:檢查條件不符 | 暫存表 CHECK CONSTRAINT 未精確對應分區邊界 | 動態產生 CHECK CONSTRAINT,確保 boundary < col < next_boundary |
| SPLIT/MERGE 耗時極長、封鎖 | 分區資料量過大、記錄檔增長 | 預先建立空分區、分批遷移、簡單復原模式暫時切換 |
| 查詢未消除分區 | 條件非 SARGable、參數化導致參數嗅探 | 重寫條件、使用 OPTION (RECOMPILE)、強制參數化關閉 |
| 歸檔後身分識別欄位衝突 | SWITCH OUT 保留身分識別值,歸檔表同樣有 IDENTITY | 歸檔表移除 IDENTITY,或使用 SEQUENCE |
TRUNCATE TABLE ... PARTITION、資料壓縮、篩選索引、稀疏欄位。TRUNCATE TABLE WITH (PARTITIONS (1,3,5))、DBCC CHECKTABLE ... PARTITION、R 服務整合。SQL Server 2005 表分區功能雖較新版本簡略,但掌握 滑動視窗自動化、對齊索引維護、統計資料管理、分區消除查詢撰寫 等核心技巧,即可支撐 TB 級資料量的高效運作。建議建立標準化維護流程、監控儀表板與演練腳本,讓分區管理成為常態化、低風險的作業。