1. 程式人生 > >(4.18)資料壓縮

(4.18)資料壓縮

轉自:https://www.cnblogs.com/chinesern/p/8886878.html

SqlServer資料壓縮測試

環境說明

作業系統:WIN SERVER 2012 R2 Standard
資料庫系統: SQLSERVER 2016 SP1 Enterprise Evaluation Edition 硬體環境:CPU E7-8891 V3 2.79GHZ 80 CORES 記憶體 256GB

1.SqlServer資料壓縮介紹

行壓縮
啟用壓縮只會更改與資料型別相關聯的資料的物理儲存格式,而不會更改其語法或語義。 當對一個或多個表啟用壓縮時,不需要更改應用程式。
新的記錄儲存格式主要有以下更改:
 1.減少了與記錄相關聯的元資料開銷。 此元資料為有關列、列長度和偏移量的資訊。 在某些情況下,元資料開銷可能大於舊的儲存格式。
 2.對於數值型別(例如, integer、 decimal和 float)和基於數值的型別(例如, datetime 和 money)使用可變長度儲存格式。
 3.通過使用不儲存空字元的可變長度格式來儲存定長字串。



頁壓縮 
頁壓縮包含行壓縮,以及字首壓縮和字典壓縮,當使用頁壓縮時,將僅使用行壓縮來壓縮索引的非葉級別頁,行壓縮上面已經介紹.
頁壓縮對錶、表分割槽、索引和索引分割槽都是類似的。 
但對於字串和其他資料型別而言,字首壓縮和字典壓縮的原理都是相同的。

字首壓縮      
對於要壓縮的每一頁,字首壓縮採用以下步驟: 
1 對於每一列,將確定一個值,此值可用於減少每一列中的值的儲存空間。
2 將建立表示每一列的字首值的行,並將其儲存在緊隨頁頭之後的壓縮資訊(CI) 結構中。
3 列中重複的字首值將由指向對應字首的引用進行替換。如果行中的值與所選字首值並不完全匹配,則仍會指示存在部分匹配。 

2.建立表結構
#建立一個具有行壓縮的表
use his;
/****** Object:  Table [dbo].[test_compress]    Script Date: 2018/3/7 13:46:43 ******/
SET ANSI_NULLS OFF
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[test_compress_ROW](
    ...
    ...
    ...
 CONSTRAINT [test_compress_ROW_pk] PRIMARY KEY CLUSTERED 
(
    ...
    ...
    ...
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ,DATA_COMPRESSION=ROW) --壓縮選項 ON [PRIMARY] ) ON [PRIMARY] GO 3.測試非壓縮表的效能 #可以用如下語句重新配置壓縮選項,設定為不壓縮 alter table [test_compress_ROW] rebuild with (data_compression=none) #模擬在非壓縮表上插入100w條資料,並輸出效能資料
set statistics io on set statistics time on insert into [test_compress_ROW] select top 1000000 * from [dbo].[test_origin] order by id SQL Server 分析和編譯時間: 表 'test_compress_ROW'。掃描計數 0,邏輯讀取 286554 次,物理讀取 0 次,預讀 0 次, lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 表 'test_origin'。掃描計數 1,邏輯讀取 56317 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次, lob 物理讀取 0 次,lob 預讀 0 次。 SQL Server 執行時間: CPU 時間 = 9407 毫秒,佔用時間 = 12560 毫秒。 (1000000 行受影響) #檢視非壓縮表上的空間佔用 exec sp_spaceused [test_compress_ROW] name rows reserved data index_size unused test_compress_ROW 1000000 447648 KB 444448 KB 3032 KB 168 KB #前面的插入已經將資料寫入到快取,為了確保真實還原效能問題,我們需要關閉SQL Server自身的執行計劃及快取。清除快取。 DBCC DROPCLEANBUFFERS --清除緩衝區 DBCC FREEPROCCACHE --刪除計劃快取記憶體中的元素 #在非壓縮表上執行select 並記錄效能統計資訊 #這裡查詢10000條資料作為例子,資料塊多更能反映效能對比 select top 10000 * from test_compress_ROW SQL Server 分析和編譯時間: CPU 時間 = 0 毫秒,佔用時間 = 4 毫秒。 (10000 行受影響) 表 'test_compress_ROW'。掃描計數 1,邏輯讀取 575 次,物理讀取 1 次,預讀 5424 次, lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 SQL Server 執行時間: CPU 時間 = 93 毫秒,佔用時間 = 870 毫秒。 4. 測試行壓縮表的效能 #清空資料 truncate table [test_compress_ROW] #可以用如下語句重新配置壓縮選項,設定為行壓縮 alter table [test_compress_ROW] rebuild with (data_compression=row) #模擬在行壓縮表上插入100w條資料,並輸出效能資料 set statistics io on set statistics time on insert into [test_compress_ROW] select top 1000000 * from [dbo].[test_origin] order by [backupdate],[sysdate],[sno],[serverid] SQL Server 分析和編譯時間: CPU 時間 = 0 毫秒,佔用時間 = 9 毫秒。 表 'test_compress_ROW'。掃描計數 0,邏輯讀取 107897 次,物理讀取 0 次,預讀 0 次, lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 表 'test_origin'。掃描計數 1,邏輯讀取 56317 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次, lob 物理讀取 0 次,lob 預讀 0 次。 SQL Server 執行時間: CPU 時間 = 7109 毫秒,佔用時間 = 7314 毫秒。 (1000000 行受影響) #檢視頁壓縮表上的空間佔用 exec sp_spaceused [test_compress_ROW] name rows reserved data index_size unused test_compress_ROW 1000000 128200 KB 127728 KB 408 KB 64 KB #前面的插入已經將資料寫入到快取,為了確保真實還原效能問題,我們需要關閉SQL Server自身的執行計劃及快取。清除快取。 DBCC DROPCLEANBUFFERS --清除緩衝區 DBCC FREEPROCCACHE --刪除計劃快取記憶體中的元素 #在頁壓縮表上執行select 並記錄效能統計資訊 #這裡查詢10000條資料作為例子,資料塊多更能反映效能對比 select top 10000 * from test_compress_ROW SQL Server 分析和編譯時間: CPU 時間 = 0 毫秒,佔用時間 = 4 毫秒。 (10000 行受影響) 表 'test_compress_ROW'。掃描計數 1,邏輯讀取 235 次,物理讀取 1 次,預讀 4952 次, lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 SQL Server 執行時間: CPU 時間 = 156 毫秒,佔用時間 = 553 毫秒。 5.測試頁壓縮表的效能 #清空資料 truncate table [test_compress_ROW] #可以用如下語句重新配置壓縮選項,設定為行壓縮 alter table [test_compress_ROW] rebuild with (data_compression=page) #模擬在頁壓縮表上插入100w條資料,並輸出效能資料 set statistics io on set statistics time on insert into [test_compress_ROW] select top 1000000 * from [dbo].[test_origin] order by [backupdate],[sysdate],[sno],[serverid] SQL Server 分析和編譯時間: CPU 時間 = 0 毫秒,佔用時間 = 0 毫秒。 SQL Server 分析和編譯時間: CPU 時間 = 0 毫秒,佔用時間 = 8 毫秒。 表 'test_compress_ROW'。掃描計數 0,邏輯讀取 80357 次,物理讀取 0 次,預讀 0 次, lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 表 'test_origin'。掃描計數 1,邏輯讀取 56317 次,物理讀取 0 次,預讀 0 次, lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 SQL Server 執行時間: CPU 時間 = 19156 毫秒,佔用時間 = 19206 毫秒。 (1000000 行受影響) #檢視頁壓縮表上的空間佔用 exec sp_spaceused [test_compress_ROW] name rows reserved data index_size unused test_compress_ROW 1000000 172232 KB 171600 KB 544 KB 88 KB #前面的插入已經將資料寫入到快取,為了確保真實還原效能問題,我們需要關閉SQL Server自身的執行計劃及快取。清除快取。 DBCC DROPCLEANBUFFERS --清除緩衝區 DBCC FREEPROCCACHE --刪除計劃快取記憶體中的元素 #在頁壓縮表上執行select 並記錄效能統計資訊 #這裡查詢10000條資料作為例子,資料塊多更能反映效能對比 select top 10000 * from test_compress_ROW SQL Server 分析和編譯時間: CPU 時間 = 0 毫秒,佔用時間 = 4 毫秒。 (10000 行受影響) 表 'test_compress_ROW'。掃描計數 1,邏輯讀取 172 次,物理讀取 1 次,預讀 5248 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 SQL Server 執行時間: CPU 時間 = 203 毫秒,佔用時間 = 834 毫秒。。

 

 

6.效能資料對比

6.1資料大小對比
無壓縮 行壓縮 行壓縮比例 資料大小(頁壓縮) 頁壓縮比例
447648KB 172232KB 38.5% 128200KB 28.6%

可以看到:頁壓縮的資料壓縮比更佳!

6.2 insert cpu效能對比
無壓縮 行壓縮 頁壓縮
CPU 時間 = 9407 毫秒 CPU 時間 = 7109 毫秒 CPU 時間 = 19156 毫秒

可以看到:寫入資料時行壓縮和頁壓縮都需要壓縮操作,所以cpu佔用明顯要高出許多!頁壓縮的cpu佔用明顯要高出許多!

6.3 select cpu效能對比

無壓縮 行壓縮 頁壓縮
CPU 時間 = 93 毫秒 CPU 時間 = 156 毫秒 CPU 時間 = 203 毫秒

可以看到 讀取資料時行壓縮和頁壓縮都需要解壓操作,所以cpu佔用明顯要高出許多!其中頁壓縮cpu最高!

6.3 select io效能對比

無壓縮 行壓縮 頁壓縮
邏輯讀取 575 次,物理讀取 1 次,預讀 5424 次 邏輯讀取 235 次,物理讀取 1 次,預讀 4952 次 邏輯讀取 172 次,物理讀取 1 次,預讀 5248 次

可以看到 讀取資料時行壓縮和頁壓縮的邏輯讀比非壓縮的情況要優化很多,頁壓縮讀取的資料塊最少,io效能最好!

7.總結以及建議

1.與業務商定歸檔資料日期界限
2.拆分資料庫,早於界限日期為節點歸檔歷史資料,因為這部分資料屬於靜止冷資料,比較適合設定成為頁壓縮模式
3.定期將資料遷移到歸檔資料庫
4.晚於界限日期的資料設定為行壓縮模式,因為涉及到insert的問題 5.備份策略:完整--差異--日誌

8.注意事項

1.資料壓縮功能僅在SQLSERVER2008以後的企業版和開發版中可用

2.資料壓縮可以讓一張資料頁儲存更多的資料行,但是並不能改變單行資料最長8060位元組這一限制。

3.在一張已經設定了資料壓縮的表上建立聚簇索引時,聚簇索引預設繼承原表上的壓縮選項

4.在未設定聚簇索引的表上設定頁面壓縮時,只有以下情況才會獲得頁面壓縮的實際效果:
    a.資料使用BULK INSERT語法新增到表中
    b.資料使用INSERT INTO ... WITH (TABLOCK)語法新增到表中
    c.執行帶有頁面壓縮選項的ALTER TABLE ... REBUILD命令 5.在未設定聚簇索引的表上更改壓縮選項,會導致該表上所有非聚簇索引都需要重建,因為這些非聚簇索引指向的資料行地址已經都發生了改變。 6.在改變壓縮選項時所需要的臨時空間大小與建立索引是所需要的空間是一樣的,因此對於分割槽表,我們可以逐個分割槽設定壓縮選項來減少臨時空間的需求壓力。 7.SQL Server 2008的壓縮選項是工作在儲存引擎層的,對於SQL Server的其他部件來說這一特性是透明的,因此當我們用BULK LOAD的方式 將外面的資料匯入SQL Server時,會顯著的增加CPU的工作載荷,同時將以壓縮的資料表匯出到外部檔案時,可能會消耗比原來多很多的空間。