SQL Server內建的HTAP技術

ITPUB社群發表於2022-12-29

SQL Server內建的HTAP技術

目錄

  • 背景
  • SQL Server在OLAP上的發展
  • SQL Server的初代HTAP
  • SQL Server逐漸增強的HTAP
  • SQL Server列存總結
  • HTAP發展

 

 

 

背景

2005年,Gartner正式提出了HTAP這一概念,並且迅速引起了一些企業的關注,被視為是未來資料發展的重要趨勢之一。

到了2014年,Gartner又對HTAP資料庫給出了明確的定義:混合事務/分析處理(HTAP)是一種新興的應用體系結構,相容兩種業務場景。

混合負載(HTAP Hybrid Transactional/Analytical Processing)是在保留原有線上交易功能的同時,強調了資料庫原生計算分析的能力。

HTAP體系架構解決的一個問題是 傳統的資料倉儲做資料分析的時效性問題,傳統資料倉儲架構需要用ETL工具從各種業務資料來源(oltp)抽取資料到資料倉儲(olap)進行跑批分析,這個時效大概是T+1。

傳統資料類專案,如資料倉儲、資料集市等其他資料應用類專案有跑批日期的概念,即在T+1日跑T日的交易資料,直白的說就是在第二天跑昨天的交易。

T指的是每天或者每一個交易日,我們經常說的跑批日期也是T日的資料。

無論是過去的傳統數倉,還是現在的大資料技術棧,都存在這個時效性問題。HTAP體系架構的做法是,同時支援OLTP和OLAP場景,基於創新的計算儲存框架,在同一份資料上保證事務的同時支援實時分析,省去費時的ETL過程。

 

 

 

SQL Server在OLAP上的發展

過去,SQL Server自帶完整的數倉服務套件 ,方便使用者搭建傳統數倉,SQL Server企業版和資料中心版本身提供了三個服務

  • 做資料ETL的SQL Server整合服務(SSIS)
  • 做報表的SQL Server報表服務(SSRS)
  • 做資料多維分析的SQL Server 分析服務(SSAS   olap引擎)

相信大家在SQL Server安裝介面看到過上面幾個服務的安裝選項。

後來,為了處理更大的資料量,微軟推出SQL Server並行資料倉儲(PDW),使用多個SQL Server資料庫伺服器在大規模並行處理架構下儲存和處理資料。

再到最近十年,隨著大資料技術棧發展迅猛,微軟推出PolyBase用來整合SQL Server和Hadoop。

但是,以上技術還是需要ETL過程,存在時效性問題。

 

 

SQL Server的初代HTAP

初代HTAP首次出現在SQL Server2012版本,最初設計的目標,僅僅為了在OLTP中提供數倉場景下的OLAP能力,讓使用者可以直接在一個DBMS的行存表上建列存索引然後執行分析型負載,省去費時的ETL過程。

面對這樣的目標,SQL Server2012提供的是一個面向OLAP的列存引擎,對應上層的介面就是Read-Only Columnstore Index,即在一個行存表上建立列存索引之後,這個表變為只讀。

列存的儲存格式很簡單,每100萬行組成一個Row Group,Row Group中每一個欄位組成一個Column Segment,每個Column Segment的後設資料儲存在系統表中。列存索引只提供全表掃描。

 

圖3-1

這樣的設計,有兩個問題:

  1. 整個表都不支援更新,只讀狀態
  2. 列存索引只能是非聚集列存索引,不能是聚集列存索引

 

 

SQL Server逐漸增強的HTAP

到了SQL Server2014和SQL Server2016這兩個版本,微軟逐漸增強了列存引擎的能力,解決了初代HTAP的兩個缺點,開始支援更新,並支援表中只有列索引一份資料即聚集列存索引。

這時候,一個資料庫融合了3種儲存引擎,分別是:

  • Apollo引擎:列存引擎,面向olap
  • 傳統引擎:行存引擎,面向oltp,B+樹或堆結構
  • hekaton引擎:純記憶體行存引擎,面向oltp ,bwtree結構

 

圖4-1

圖4-2

 

為了支援更新,SQL Server引入了delta store、delete flag、rowid。

Delete Flag

在列存索引裡刪除一行資料時,實際上只是對這行資料加一個delete flag標記(bitmap標記),並不會物理刪除這行資料

 

Delta Store

是相對磁碟上的列存Main Store來說的,用於快取Insert。

Delta Store由Delta rowgroup實現,所有Delta rowgroup都統稱為Delta Store,有些文獻也叫tail index(下文中Delta Store 和 Delta rowgroup是同一個意思)

所有的rowgroup也統稱為Main Store(下文中Main Store 和 rowgroup是同一個意思)

Delta Store在結構上是聚集 B樹索引,提供熱資料的原地更新刪除,為Main Store做緩衝。

 

RowID

由列存引擎生成,用來在列存索引中唯一標記一行資料。

列存rowid在資料行插入到rowgroup時候生成,這個rowid一直到資料行被刪除都不會改變。

當行存和列存組合時,需要在行存新增一個欄位來儲存這個列存rowid,這樣來使列存和行存通訊。

 

行存中儲存全量資料,列存分為Delta Store和Main Store,其中Main Store以列存的形式儲存絕大部分資料,以Row Group為單位劃分,每個Row Group對應行存中一定數量的記錄。

假設使用者建了一個行存索引和列存索引組合的表,事務插入資料時,會同時插入行存和Delta Store,Delta Store達到100W行閾值後凍結,會將其中較冷的資料遷移到Main Store,

冷熱通過統計資訊來判斷。遷移過程中也會由新的Delta Store來快取Insert。

遷移分為兩個階段:

  • 第一階段:在一個事務中完成,將Delta Store冷記錄遷移到Main Store,在Main Store中把遷移過來的冷記錄標記delete flag刪除並分配RowID。事務提交後遷移的部分在列存索引中不可見,但在Delta Store中依然可見,資料是一致的,這時Delta Store中冷記錄並沒刪除。
  • 第二階段:在一些小事務中完成,每個事務將第一階段遷移的冷記錄從Delta Store中刪除,一個事務刪一條記錄,將對應的RowID更新到行存,並在Main Store中刪除這條記錄通過delete flag標記,事務提交後這條記錄在列存索引中可見,但在Delta Store中不可見,資料也是一致的。

SQL Server從兩個方面來減少資料遷移對行存效能的影響

  • 第一方面:第二階段更新行存中RowID時不記日誌,資料庫故障恢復時通過掃描列存重建行存RowID,減少日誌開銷。
  • 第二方面:第二階段每個事務只處理一條記錄,減少與前臺事務的寫-寫衝突(將對應的RowID更新到行存,如果有別的前臺事務也要update行存的這條記錄,會造成寫-寫衝突)。

 

 

事務刪除資料時,如果記錄在Delta Store中,則直接在行存和Delta Store中刪除,如果記錄在Main Store中,則需要根據行存中儲存的RowID在Main Store中通過全表掃描把對應記錄通過delete flag標記刪除。

為了優化全表掃描刪除的效能,SQL Server引入了Delete Buffer,將多個刪除快取,然後在一次全表掃描中批量刪除

 

圖4-3

圖4-4

 

Main Store中標記刪除的記錄太多也會影響scan的效能,也會帶來額外的記憶體開銷,因此需要進行重整。

列存索引的重整由Row Group中標記刪除的比例觸發(90%),由後臺任務將觸發重整的Row Group中的有效記錄重新插入Delta Store中,而重整的Row Group則被tuple-mover後臺執行緒回收。

 

 

事務更新資料時,通過先刪除 + 後插入實現,上文已經說了刪除 和插入的實現方式,這裡不再敘述。

 

事務查詢資料時,列存引擎需要掃描Main Store,並根據delete flag剔除已刪除資料,當第一次建列存索引時,列存引擎還需要通過Delta Store從行存表中獲取未遷移到Main Store的資料,

然後利用bulk load,把未遷移到Main Store的行存資料不經過Delta Store直接遷移到Main Store。

 

圖4-5

 

 

 

SQL Server列存總結

在概括SQL Server列存設計的優缺點之前,首先要看下數倉場景下更新的特點,這會影響到整個儲存設計。

數倉場景下更新的特點,更新中絕大部分的是Insert,只包含極少數的Update和Delete。

並且列存中原地Update的成本很高,所以Update的實現一般是一次Delete加上一次Insert。因此支援更新實際上只需要考慮Insert的效能,Delete的效能並不是很重要。

現在大部分的列存引擎普遍都會選擇Delta-Main架構,因為本身按列儲存就不利於更新,因此需要使用Delta快取架構來解決更新的問題。

 

SQL Server列存的優缺點

優點:

  • 通過引入delta store、delete flag、rowid,讓列存索引以append-only的方式更新,保證跨行存和列存索引上事務的ACID。

缺點:

  • 插入資料到列存、Row Group重整、更新列存資料帶來一定開銷,這個開銷就是都需要更新行存中的RowID,因此都會和行存的OLTP事務產生競爭,影響系統整體效能,這個是SQL Server行存和列存緊耦合導致的。

 

根據數倉場景的特點,SQL Server列存的開銷其實可以接受,然後使用類Delta-Main架構也是比較主流的做法,但是到了HTAP的場景,整個資料庫需要支撐高併發的查詢和更新,列存的開銷就會被放大。

在這方面,SQL Server也提供了很多優化方案,比如使用Mapping Index來減輕更新行存中的RowID的開銷問題。

 

有同學會問SQL Server2014開始支援聚集列存索引,整個表只有一個列存索引作為primary index,就不會有更新行存RowID這個開銷,但是資料庫一般也需要唯一約束、外來鍵約束等,要維護這些約束就需要行存B樹索引來輔助。

所以,最後還是要行存和列存組合來使用。

 

 

 

HTAP發展

最後,從SQL Server的發展來看,一份表資料兩種儲存格式,兩種儲存引擎處理,查詢時優化器自動選擇儲存引擎執行,對使用者透明,這些特性讓SQL Server走在了前列

當然,其他商業資料庫和開源資料庫也在向HTAP方向發展,例如Oracle、GreenPlum、SAP HANA等等

還有,國產資料庫的兩大代表PingCAP、OceanBase,在成立之初就定位為新一代分散式的HTAP資料庫,通過行存和列存鬆耦合來解決效能問題,新型的分散式架構確實比傳統資料庫更勝一籌。

 

 

 

本文版權歸作者所有,未經作者同意不得轉載。

相關文章