數據壓縮 : 簡要

来源:http://www.cnblogs.com/Joe-T/archive/2016/07/13/5666756.html
-Advertisement-
Play Games

1. 決定壓縮哪些對象 通過sp_estimate_data_compression_savings 評估在ROW和PAGE壓縮時分別節省的空間量。 表包含如下數據模式時,會有較好的壓縮效果: 數字類型的列和固定長度的字元類型數據,但兩者的大多數值都不會用到此類型的所有位元組。如INT列的值大多數少於 ...


1. 決定壓縮哪些對象

通過sp_estimate_data_compression_savings 評估在ROW和PAGE壓縮時分別節省的空間量。

表包含如下數據模式時,會有較好的壓縮效果:

  • 數字類型的列和固定長度的字元類型數據,但兩者的大多數值都不會用到此類型的所有位元組。如INT列的值大多數少於1000.
  • 允許為NULL的列有很多NULL值
  • 列值中有很多一樣的值或者相同的首碼。

表包含如下數據模式時,壓縮效果較差:

  • 數字類型的列和固定長度的字元類型數據,但是兩者的大多數值都會用盡此類型的所有位元組。
  • 非常少量的重覆值
  • 重覆值不具有相同的首碼
  • 數據存儲在行外
  • FILESTREAM數據

 

2. 評估應用負載模式

被壓縮的頁在磁碟和記憶體都是壓縮的下麵兩種情況下會被解壓縮(不是整頁解壓縮,只解壓縮相關的數據):

  • 因為查詢中的filtering, sorting, joining操作而被讀取
  • 被應用程式更新

解壓縮會消耗CPU,但是數據壓縮會減少物理IO和邏輯IO,同時會提高緩存效率。對於數據掃描操作,減少的IO量非常可觀。對於單個的查找操作,減少的IO量較少。

行壓縮導致的CPU開銷通常不會超過10%。如果當前的系統資源充足,增加10%CPU毫無壓力的話,建議所有的表都啟用行壓縮。

頁壓縮比行壓縮的CPU開銷高一些,所以確定是否使用頁壓縮會困難一些。可以通過一些簡單的準則來幫助我們判斷:

  • 從那些不常用的表和索引開始
  • 如果系統沒有足夠的CPU餘量,不要使用頁壓縮
  • 因為 filtering, joins, aggregates和sorting操作使用解壓縮後的數據,所以數據壓縮對這類查詢沒有太多幫助。如果工作負載主要由非常複雜的查詢(多表JOIN,複雜聚合)組成,頁壓縮不會提高性能,最主要是節省存儲空間。
  • 大型數據倉庫系統中,掃描性能是其重點,同時存儲設備的成本較高,在CPU性能允許下,建議對所有表使用頁壓縮。

可以通過兩個更細的度量值來幫我們評估使用何種數據壓縮方式:

  • U:特定對象(表、索引或者分區)的更新操作占所有操作的百分比。越低越適合頁壓縮。
  • S:特定對象(表、索引或者分區)的掃描操作占所有操作的百分比。越高越適合頁壓縮。

通過如下腳本查詢資料庫所有對象的U:

SELECT o.name AS [Table_Name], x.name AS [Index_Name],

       i.partition_number AS [Partition],

       i.index_id AS [Index_ID], x.type_desc AS [Index_Type],

       i.leaf_update_count * 100.0 /

           (i.range_scan_count + i.leaf_insert_count

            + i.leaf_delete_count + i.leaf_update_count

            + i.leaf_page_merge_count + i.singleton_lookup_count

           ) AS [Percent_Update]

FROM sys.dm_db_index_operational_stats (db_id(), NULL, NULL, NULL) i

JOIN sys.objects o ON o.object_id = i.object_id

JOIN sys.indexes x ON x.object_id = i.object_id AND x.index_id = i.index_id

WHERE (i.range_scan_count + i.leaf_insert_count

       + i.leaf_delete_count + leaf_update_count

       + i.leaf_page_merge_count + i.singleton_lookup_count) != 0

AND objectproperty(i.object_id,'IsUserTable') = 1

ORDER BY [Percent_Update] ASC

通過如下腳本查詢資料庫所有對象的S:

SELECT o.name AS [Table_Name], x.name AS [Index_Name],

       i.partition_number AS [Partition],

       i.index_id AS [Index_ID], x.type_desc AS [Index_Type],

       i.range_scan_count * 100.0 /

           (i.range_scan_count + i.leaf_insert_count

            + i.leaf_delete_count + i.leaf_update_count

            + i.leaf_page_merge_count + i.singleton_lookup_count

           ) AS [Percent_Scan]

FROM sys.dm_db_index_operational_stats (db_id(), NULL, NULL, NULL) i

JOIN sys.objects o ON o.object_id = i.object_id

JOIN sys.indexes x ON x.object_id = i.object_id AND x.index_id = i.index_id

WHERE (i.range_scan_count + i.leaf_insert_count

       + i.leaf_delete_count + leaf_update_count

       + i.leaf_page_merge_count + i.singleton_lookup_count) != 0

AND objectproperty(i.object_id,'IsUserTable') = 1

ORDER BY [Percent_Scan] DESC

 

這兩個查詢用到了DMV sys.dm_db_index_operational_stats。DMV只是記錄上次SQL Server實例啟動以來的積累值,所以在實際應用中要選擇一個合適的時間來查詢。

通常U<20%和S>75%會是比較合理的考慮啟用壓縮的出發點,但是對於只插入有序數據的流水錶,頁壓縮會比較合適(即使S值很低)。

 

3. 評估資源需求

    使用ALTER TABLE… REBUILD和ALTER INDEX … REBUILD對錶和索引啟用壓縮,其它原理和重建索引是一樣的。通常需要的資源包括空間、CPU、IO、空間需求

在壓縮過程中,已壓縮的表和未壓縮表是並存的,只有完成壓縮後,未壓縮的表才會被刪除並釋放空間。如果Rebuild是ONLINE的話,則還有Mapping Index需要額外的空間。

事務的空間需求由壓縮方式是否是ONLINE(ON or OFF)和資料庫的恢復模式決定。

當SORT_IN_TEMPDB=ON時(推薦為ON),為了實現併發DML操作,會在tempdb中Mapping index的內部結構來映射舊書簽和新書簽的關係。對於版本化存儲的,tempdb的使用量由併發DML操作所涉及的數據量和事務時間長度決定。

通常行壓縮操作的CPU開銷是重建一個索引的1.5倍左右,頁壓縮是它的2到5倍。ONLINE模式還需要額外的CPU資源。Rebuild和Compress可以被並行化的,所以還要結合MAXDOP一起考慮。

並行化的註意事項:

  • SQL Server在Create/Rebuild/Compress一個索引時,使用索引首列(最左列)的統計信息確定並行操作在多個CPU間的分佈。所以當索引首列的篩選度不高,或者數據傾斜嚴重使得首列的值很少時,並行化對性能提升的幫助就很少。
  • 使用ONLINE=ON方式Compress/Rebuild堆表是單線程操作。但是壓縮和重建的表掃描操作是並行多線程的。

下表總結對比了壓縮和重建一個聚集索的資源開銷:

  • X = 壓縮或者重建前的頁數量
  • P = 壓縮後的頁數量(P < X)
  • Y = 新增和被更新的頁數據 (只適用於ONLINE=ON時併發應用所做修改)
  • M = Mapping index的大小 (基於<TEMPDB Capacity Planning>白皮書的預估值)
  • C = 重建聚集索引所需CPU時間

image

在判斷何時和怎麼壓縮數據時,下麵是一些參考點:

  • Online vs. Offline:

        Offline更快,需要的資源也更少,但是壓縮操作過程中會鎖表。Online自身也會有一些限制。

  • 一次壓縮一個table/index/partition vs. 多個操作併發:

        這個由當前資源的餘量決定,如果資源很充足,多個壓縮操作並行也可以接受的,否則最好一次一個。

  • 表壓縮操作的順序:

        從小表開始,小表壓縮需要的資源少,完成快。完成後釋放的資源也利於後續表的壓縮操作。

  • SORT_IN_TEMPDB= ON or OFF:

        推薦ON。這樣可以利用tempdb來存放和完成Mapping index操作,從而也減少用戶數據的空間需求。

壓縮操作副作用:

  • 壓縮操作包括重建操作,所以會移除表或索引上的碎片。
  • 壓縮堆表時,如果有非聚集索引存在,則:當ONLINE=OFF,索引重建是串列操作,ONLINE=ON,索引重建是並操作。

 

4. 維護壓縮數據

 

新插入數據的壓縮方式

image

*通過以頁壓縮方式重建堆表來將行級壓縮頁轉換為頁級壓縮。

**頁壓縮中,並不是所有的頁都是頁壓縮的,只有當頁壓縮節省的空間量超過一個記憶體閾值時才是。

 

更新和刪除已壓縮的行

所有對行壓縮表/分區數據行的更新會保持行壓縮格式。並不是每次對頁壓縮表/分區的數據行的更新都會導致列首碼和頁字典被重新計算,只有當在上的更新數量超過某個內部閾值時,才會重新計算。

 

輔助數據結構的行為

Table compression

Transaction log

Mapping index for rebuilding the clustered index

Sort pages for queries

Version store (with SI or RCSI isolation level)

ROW

ROW

NONE

NONE

ROW

PAGE

ROW

NONE

NONE

ROW

 

頁壓縮索引的非葉級頁是行壓縮的

索引的非葉級頁相對較小,就算應用頁級壓縮,節省的空間也不會很顯著。而對非葉級頁的訪問會很頻繁,使用行級壓縮可減少每次訪問時解壓縮成本。

 

5. 回收數據壓縮釋放的空閑空間

  1. 不回收,留著給將在的數據增長使用。這個不適合分區表(每個分區對應一人不同的文件級)的只讀分區,壓縮舊的只讀分區不會增長,壓縮可以節省大量空間。
  2. DBCC SHRINKFILE (或者DBCC SHRINKDATABASE) 。這個操作會帶來大量碎片,同時它是一個單線程操作,可能會耗時較長。
  3. 如果壓縮了一個文件組上的所有表,則新建一個文件組,然後在壓縮時將表和索引移動到新的文件組。數據移動可以通過Create/Recreate聚集索引的方式實現(如,WITH (DATA_COMPRESSION=PAGE, DROP_EXISTING=ON, SORT_IN_TEMPDB=ON) ON [FG_NEW] )。移動完數據之後,刪除原來的文件組即可。但是這種方式不能移動LOB_DATA數據到新文件組。
  4. 在新文件組上創建壓縮的表,然後將數據導入到這些表。

 

6. BULK INSERT 和數據壓縮

BULK INSERT WITH (TABLOCK)導入數據到已壓縮的表,速度最快。很明顯,這會鎖表。

壓縮數據時,BULK INSERT和創建聚集索引的順序考慮:

序號

方式

比較

1

BULK INSERT導入數據到未壓縮的堆表,然後再 CREATE CLUSTERED INDEX WITH (DATA_COMPRESSION = PAGE).

所需時間:1<2<3

2

BULK INSERT導入數據到頁壓縮的堆表,然後再  CREATE CLUSTERED INDEX

所需空間:1>2>3

3

BULK INSERT導入數據到頁壓縮的聚集索引

 

 

7. 數據壓縮和分區表維護

1. Switch操作要求目標分區(或目標表)與源分區的壓縮方式相同。

2. Split後的分區繼承原分區的壓縮方式。

3. Merger操作,被刪除的分區稱為源分區,接收數據的分區稱為目標分區:

目標分區的壓縮方式

數據合併到目標分區的方式

NONE

在Merger期間,數據會被解壓縮到目標分區

ROW

在Merger期間,數據會被轉換成行壓縮格式

PAGE

-堆表: 在Merger期間,數據會被轉換成行壓縮格式

- 聚集索引: 在Merger期間,數據會被轉換成頁壓縮格式

分區表Merger操作規則

1. LEFT RANGE時,刪除邊界值所在的分區,保留"左"側的分區,並向其移動數據

2. RIGHT RANGE時,刪除邊界值所在的分區,保留"右"分區,並向其移動數據

 

8. 數據壓縮和透明數據加密(TDE)

TDE是當數據頁寫入磁碟時加密,從磁碟中讀出頁放入到記憶體時解密。而數據壓縮/解壓縮操作是對記憶體中的頁執行的,所以數據壓縮/解壓縮總是用到解密後的頁。因此兩者之前的相互影響很小。

 

總結

1. 本文來基於白皮書<Data Compression: Strategy, Capacity Planning and Best Practices>的簡譯和總結。此白皮書是基於SQL Server 2008的。

2. 數據壓縮是一個被低估SQL Server技術,個人認為很有必要將之做為標準化最佳實踐之一。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • cocoapods簡介: cocoapods簡介: cocoapods 是iOS的類庫管理工具,可以讓開發者很方便集成各種第三方庫,而不用去網站上一個個下載,再一個個文件夾的拖進項目中,還得添加相關的系統依賴庫。只需要安裝好cocoapods,然後編寫好Podfile,最好在終端輸入一行命令,就可以 ...
  • imp 導入資料庫: 1.直接導入數據表: imp username/passwork@orcl file=d:/AA.dmp eg: imp 用戶名/密碼@orcl file=d:/dmp存放的路徑 exp導出資料庫: 1.導出多張數據表: exp username/passwork@orcl f ...
  • SQL Server2014 SP2關鍵特性 轉載自:https://blogs.msdn.microsoft.com/sqlreleaseservices/sql-2014-service-pack-2-is-now-available/ 根據SQL Server客戶的和SQL社區的反饋,SQL2 ...
  • 在前一篇博文數據壓縮簡要的基礎上,我希望把數據壓縮評估自動化。於是有了這篇博文。 白皮書推薦對符合如下條件的大型表和索引使用頁壓縮: 表或索引的掃描操作占到所有操作的75%及以上時 表或索引的更新操作占到所有操作的20%及以下時 註意,這是白皮書中的結論和建議,只做參考,最為最佳實踐的考慮點之一。 ...
  • 如果需要進行SQl Server下的SQL性能優化,需要準備以下內容: 一、SQL查詢分析器設置: 1、開啟實際執行計劃跟蹤。 2、每次執行需優化SQL前,帶上清除緩存的設置SQL。 平常在進行SQL Server性能優化時,為了確保真實還原性能問題,我們需要關閉SQL Server自身的執行計劃及 ...
  • 今天剛好需要刪除redis里的db2里的數據,我找了一下,發現這篇內容幫助我解決了問題,記錄一下。 Redis 中有刪除單個 Key 的指令 DEL,但好像沒有批量刪除 Key 的指令,不過我們可以藉助 Linux 的 xargs 指令來完成這個動作。 代碼如下: redis-cli keys “* ...
  • SQL 不同於與其他編程語言的最明顯特征是處理代碼的順序。在大數編程語言中,代碼按編碼順序被處理,但是在SQL語言中,第一個被處理的子句是FROM子句,儘管SELECT語句第一個出現,但是幾乎總是最後被處理。 每個步驟都會產生一個虛擬表,該虛擬表被用作下一個步驟的輸入。這些虛擬表對調用者(客戶端應用 ...
  • 其中tablename為表的名稱,num為要設置的新的自動遞增值,此時再Insert一條數據,自動遞增值即為num,不過num必須要大於等於現在已有的自動遞增值,否則SQL語句會執行成功,但是實際上不起作用。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...