背景
SQL Server 2008 (代號 Katmai) 引入企業版專屬的 **資料壓縮** 功能,提供 **列級壓縮 (ROW Compression)** 與 **頁級壓縮 (Page Compression)** 兩種策略,大幅降低儲存成本並提升 I/O 密集型工作負載效能。功能於 CTP6 版首度亮相,正式版隨企業版釋出。
列級壓縮 (ROW Compression):變長格式儲存固定長度型別
核心機制
- 將所有 **固定長度資料類型** (int, bigint, char, float, datetime, money 等) 以 **變長格式** 儲存,實際佔用空間依資料值大小動態調整。
- 不改變語意:應用程式完全無感,資料類型、精度、比較行為皆維持不變。
- NULL 值 **不佔用任何儲存空間** (僅在 NULL bitmap 標記)。
實際壓縮效果範例
| 欄位定義 | 資料值範圍 | 原始固定長度 | 壓縮後實際長度 | 節省空間 |
INT (4 bytes) | 0 ~ 255 | 4 bytes | 1 byte (資料) + 4 bits (位移) = 1.5 bytes | 62.5% |
CHAR(100) | "Hello" (5 字元) | 100 bytes | 5 bytes + 4 bits | 95% |
CHAR(100) | "This is a longer string" (23 字元) | 100 bytes | 23 bytes + 4 bits | 77% |
⚠ 壓縮比高度依賴 **實際資料值分布** 與 **欄位定義長度**;若值接近型別上限 (如 INT 存 20 億、CHAR(100) 存 95 字元),壓縮效益遞減。
技術細節:變長欄位位移陣列優化
- 傳統變長欄位需 2 bytes 儲存位移;SQL 2008 對 **長度 ≤ 8 bytes** 的型別優化為 **4 bits** 位移,大幅降低額外負擔。
- 這解釋了為何 INT 壓縮後佔 1.5 bytes (1 byte 資料 + 0.5 byte 位移),而非理論 1 byte。
- 預設儲存格式 (未啟用壓縮) 仍為傳統固定長度格式;啟用
ROW COMPRESSION 後切換至新格式。
頁級壓縮 (PAGE Compression):頁內資料重複刪除 + 字典編碼
核心機制
- 在 **單一 8KB 資料頁** 內,針對 **跨列的重複值** 僅儲存一次,建立 **字典 (Dictionary)**,其他位置以參考取代。
- 包含兩階段:
- 列前綴壓縮 (Row Prefix Compression):針對每欄位值的共同前綴建立字典。
- 字典壓縮 (Dictionary Compression):針對頁內任意位置的重複值建立全域字典。
- 啟用語法:
PAGE COMPRESSION (隱含包含 ROW COMPRESSION)。
適用場景與效果
| 場景 | 壓縮效果 | 說明 |
| 狀態欄位大量重複 (如 'Active', 'Pending') | 極佳 | 字典壓縮將重複字串替換為 1-2 bytes 代碼 |
| 外鍵欄位值集中分布 | 良好 | 前綴/字典雙重生效 |
| 高基數唯一值 (如 GUID, Identity) | 差 | 幾無重複,反增字典開銷 |
| 已加密/壓縮資料 (如 .zip, .jpg) | 無效/負面 | 資料熵高,無重複模式 |
壓縮效能評估工具:sp_estimate_data_compression_savings
-- 評估列級壓縮
EXEC sp_estimate_data_compression_savings 'dbo', 't1_big', NULL, NULL, 'ROW';
-- 評估頁級壓縮
EXEC sp_estimate_data_compression_savings 'dbo', 't1_big', NULL, NULL, 'PAGE';
實測範例 (6000 列, c1 INT, c2 INT, c3 CHAR(8000), 實際 c3 存 60 字元 'a')
| 指標 | 無壓縮 | ROW 壓縮 | PAGE 壓縮 |
| 保留空間 (KB) | 48,008 | 472 | 80 |
| 資料空間 (KB) | 48,000 | ~392 | ~72 |
| 壓縮率 | 基準 | **99.2%** | **99.8%** |
頁級壓縮因 c3 大量重複 'a' 字元,字典壓縮效果極致。
啟用壓縮語法
-- 建立資料表時指定
CREATE TABLE T (C1 INT, C2 CHAR(100)) WITH (DATA_COMPRESSION = PAGE);
-- 現有資料表/索引啟用 (線上操作, 需企業版)
ALTER TABLE T REBUILD WITH (DATA_COMPRESSION = ROW);
ALTER INDEX IX_T_C1 ON T REBUILD WITH (DATA_COMPRESSION = PAGE);
-- 分割表指定特定分割區
ALTER TABLE T REBUILD PARTITION = 2 WITH (DATA_COMPRESSION = PAGE);
效能影響與權衡
| 面向 | 影響 | 建議 |
| CPU | 壓縮/解壓縮增加 CPU 負載 (通常 < 10%) | CPU 有餘裕時啟用;CPU 瓶頸系統慎用 |
| I/O | 資料頁變小 → 讀寫 I/O 大幅減少、緩衝區命中率提升 | I/O 密集型 (資料倉儲、歸檔表) 效益最大 |
| 記憶體 | 緩衝區可容納更多熱資料 | 正面效益 |
| 備份/還原 | 備份檔縮小、速度加快 (搭配備份壓縮) | 維護窗口縮短 |
| 索引重建 | 重建時需解壓縮→重新壓縮,耗時較久 | 排程於低峰期 |
限制與注意事項
- **僅限企業版/開發版/評估版** (Standard Express 等不支援)。
- 系統表、檢視表、XML 索引、全文索引、FILESTREAM、稀疏欄位資料列集合不支援壓縮。
- 壓縮後資料頁無法在舊版本 (SQL 2005 及之前) 還原/附加。
- 啟用壓縮屬於 **資料定義語言 (DDL) 操作**,會取得 Sch-M 鎖,大表建議離線維護或使用線上重建 (Enterprise 版支援
ONLINE = ON)。
相關資源連結
- SQL Server 2008 Data Compression (官方白皮書)
- Data Compression: Why Do we need it? (Sunil Agarwal 部落格)
- Types of data compression in SQL Server 2008
- Estimating the space savings with data compression
- Backup Compression (SQL 2008 新增,獨立於資料壓縮)