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的工作載荷,同時將以壓縮的數據表導出到外部文件時,可能會消耗比原來多很多的空間。
