從SQL SERVER 2008開始,SQL SERVER 提供了對數據進行壓縮的功能,啟用數據壓縮無須修改應用程序。
數據壓縮可有效減少數據的占用空間,讀取和寫入相同數據花費的IO也響應減少,從而可以有效緩解IO壓力,但由於數據在讀取和寫入時需要壓縮和解壓縮,因此會消耗CPU資源,但不代表在相同負載下,啟用數據壓縮會導致CPU的使用率變高,某些操作會因為數據頁數量的減少而降低CPU資源的消耗。
可以配置數據壓縮的對象有:
1>存儲為堆的整個表。
2>存儲為聚集索引的整個表。
3>整個非聚集索引。
4>整個索引視圖。
5>對於已分區表和已分區索引,可為每個分區配置壓縮選項,且對象的各個分區的壓縮設置不必相同。
(個人理解:數據壓縮是在parition級別上使用,未分區表和未分區索引同樣可以找到一個對應的partitionID)
數據壓縮方式有兩種
1:行壓縮
2:頁壓縮
行壓縮實現:
行壓縮更改與數據類型相關聯的數據的物理存儲格式來實現壓縮:
1>減少了與記錄相關聯的元數據開銷。 此元數據為有關列、列長度和偏移量的信息。 在某些情況下,元數據開銷可能大於舊的存儲格式。
2>它對於數值類型(例如,integer、decimal 和 float)和基於數值的類型(例如,datetime 和 money)使用可變長度存儲格式。
3>它通過使用不存儲空字符的可變長度格式來存儲定長字符串。
快速理解:
對應數值類型和基於數值的類型來說,由於需要類型定義范圍內的數據,因此需要相對較大的定長空間,如BIGINT占用8個字節,但對於值1來說,只需要一個字節便可以存放,啟用行壓縮便可以節省7個字節的空間;對於定長數據類型,如果存放的數據未達到指定長度,會補空字符來填滿,如類型CHAR(200)用來存放字符串"1"會花費200個字節,但啟用行壓縮后,會將填充的空字符移除,只需要1個字節便可以存放。而對於類型bit來說,除自身消耗的空間外,還需要額外的4個bit來存放元數據,因此也可以從行壓縮中獲益。
行壓縮影響的數據類型可參考http://msdn.microsoft.com/zh-cn/library/cc280576.aspx
頁壓縮實現:
頁壓縮是在行壓縮的基礎上進行前綴壓縮,然后再進行字典壓縮
前綴壓縮:前綴壓縮針對頁中的各列來進行壓縮,首先從列中選取出一個前綴值(不要求頁中每一行的該列的值都包含此前綴)存放在頁頭,然后使用該前綴替換頁中每一行的該列值,如提起前綴為aabbcc,對應值aabbccdd則替換為6dd,對應值aadd則替換為2dd,對應值ccbbdd則替換成0ccbbdd,對應值aabbcc則替換成[],每行會生成一個前綴來處理。
字典壓縮:字典壓縮是在前綴壓縮完成后,搜索頁面上任意位置的重復值,然后將它們存儲在 CI 區域中。 與前綴壓縮不同,字典壓縮不局限於一列。 字典壓縮可以替換頁面上任意位置出現的重復值。
當表和索引使用頁壓縮后,對於一個新的頁面,插入數據行時會對該行啟用行壓縮,直到該頁已滿無法存放新增加的行時,才會使用頁壓縮的算法計算啟用頁壓縮是否能存放新增加的行,如果可以存放,則對該頁進行頁壓縮並將新增加的行放到該頁,如果不能存放,則不對該頁啟用頁壓縮,申請新頁來存放新行。
在SQL SERVER 2012中,SQL Server 使用 Unicode 標准壓縮方案 (Standard Compression Scheme for Unicode, SCSU) 算法實現來壓縮在行或頁壓縮對象中存儲的 Unicode 值。 對於這些壓縮對象,Unicode 壓縮對於 nchar(n) 和 nvarchar(n) 列而言是自動的。 數據庫引擎 將 Unicode 數據存儲為 2 個字節,無論區域設置如何。 這稱為 UCS-2 編碼。 對於某些區域設置而言,在 SQL Server 中實現 SCSU 壓縮可節省高達 50% 的存儲空間。
數據壓縮Demo
--============================================================================================================================= --========================================================= --判斷表和索引是否啟用壓縮和壓縮類型 --宋桑提供 SELECT DISTINCT SCHEMA_NAME(o.schema_id) + '.' + OBJECT_NAME(o.object_id) AS TableName, i.name AS IndexName, p.data_compression_desc AS CompressionType, i.type_desc AS StorageType FROM sys.partitions p with(nolock) INNER JOIN sys.objects o with(nolock) ON p.object_id = o.object_id JOIN sys.indexes i ON p.object_id = i.object_id AND i.index_id = p.index_id WHERE p.data_compression > 0 AND SCHEMA_NAME(o.schema_id) <> 'SYS' --========================================================= --使用采樣來預估數據對象啟用壓縮前后的空間使用 --參考鏈接:http://msdn.microsoft.com/zh-cn/library/cc280574.aspx --PS:該算法只能起參考作用,數據壓縮得到的空間可能比預估的要大很多 EXEC sp_estimate_data_compression_savings 'dbo', 'TB', NULL, NULL, 'ROW' ; --========================================================= --對表使用數據壓縮 ALTER TABLE <table_name> REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = PAGE|ROW) --========================================================= --對表中特定分區指定壓縮 ALTER TABLE <table_name> REBUILD PARTITION = 1 WITH (DATA_COMPRESSION = PAGE|ROW) --========================================================= --對表中多個特定分區指定壓縮 ALTER TABLE <table_name> REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = PAGE ON PARTITIONS(<range>), ... ) --========================================================= --在新建索引時指定壓縮 CREATE CLUSTERED INDEX [CLX_ID] ON [dbo].[TB2] ( [ID] ASC )WITH (DATA_COMPRESSION = { NONE | ROW | PAGE}) ON [PRIMARY] GO --========================================================= --使用重建索引來進行壓縮 ALTER INDEX [CLX_ID] ON [dbo].[TB2] REBUILD PARTITION = ALL WITH ( DATA_COMPRESSION = { NONE | ROW | PAGE }) --=============================================================================================================================
壓縮試驗:
壓縮表定義為:
CREATE TABLE [dbo].[TB1]( [id] [bigint] IDENTITY(1,1) PRIMARY KEY, [star_uid] [bigint] NOT NULL, [source_uid] [bigint] NOT NULL, [site_type] [tinyint] NOT NULL, [site_server_type] [tinyint] NOT NULL, [site_id] [bigint] NOT NULL, [count] [int] NOT NULL, [create_date] [bigint] NOT NULL, ) ON [PRIMARY]
壓縮前占用空間:7309288KB
壓縮后占用空間:2594624KB
壓縮使用時間:3分58秒
壓縮環境:8Core 32G 4塊SAS(15000轉4盤片)做RAID 10
--未完待續
參考鏈接:http://msdn.microsoft.com/zh-cn/library/cc280449.aspx
慣例上圖引狼