SQL Server 列儲存索引概述
第一次接觸ColumnStore是在2017年,資料庫環境是SQL Server 2012,Microsoft 第一次在SQL Server 2012中推廣列儲存索引,到現在的SQL Server 2017環境,列儲存索引發生了很大的變化。簡單來說,列儲存索引是資料倉庫中用於查詢和儲存大型事實表和維度表的標準方法,它使用基於列的資料儲存格式和高於傳統行儲存格式10倍的壓縮率,不僅使得列儲存索引得查詢效能比傳統的面向行的儲存高出約10倍,而且儲存空間得消耗會減少約10倍。
一,列儲存索引的基本概念
列儲存索引的實現機制,從頂層設計來說,是先把資料分組,在每一個分組中,再按照列來儲存資料。
1,列儲存、行儲存和增量儲存的概念
行儲存(Row Store):是傳統的資料儲存格式,以行格式來實現。在物理儲存上,資料按照行來儲存,一行包含所有的資料列。
列儲存(Column Store):是以列格式來儲存資料,各個列單獨儲存。列儲存索引實際上以列儲存格式來儲存“大多數”資料,部分資料以行儲存格式儲存。在列儲存格式中,資料以列為單位來壓縮和解壓縮,在一行資料中,對於需要的資料列進行解壓縮和查詢,而對於不需要的列,可以忽略,這樣可以快速掃描大型表的整個列。
增量儲存(Delta Store):是以行儲存格式儲存的聚集索引,列儲存索引會把一些資料儲存為行儲存格式,這些資料被稱為deltastore( 增量儲存區),它用於儲存在一次插入操作中因為數量太少而無法壓縮到列儲存中的行,每個增量行組都是通過行版本的聚集B-Tree索引來實現的。
2,行組(Rowgroup)
行組是基礎表中的一組資料行,這些資料行作為列儲存索引的一個片段,列儲存索引對該行組中的所有資料行做為一個整體進行壓縮和查詢。為了獲得高效能和高壓縮率,columnstore索引把表切成行組,然後對每個行組中的各個資料列進行壓縮。行組中的行數必須足夠大,閾值是100萬行,以提高壓縮率,壓縮之後的資料最終以列儲存格式進行儲存。
3,列段(column segment)
列段是行組中的每一列構成的資料,對於每一個行組,每一列都有一個列段;每一個列段都壓縮到一起,儲存到硬碟上。
二,列儲存索引架構概述
聚集列儲存索引是整個資料表的物理儲存,為了減少列段的碎片並提高效能,columnstore索引可能會將一些資料臨時儲存到一個稱為deltastore的聚集索引中。
deltastore是一個以RowStore格式儲存的聚集索引,儲存的資料分為兩部分:一部分是新增的資料,另一部分是刪除的資料。
- 對於新增的資料,該資料邏輯上存在於表中,但是,實際上,並不在列儲存中,而是以rowstore格式儲存在deltastore中。
- 對於被刪除的資料,邏輯上被標記為刪除,但是,實際上,並沒有從列儲存中刪除,也就是說物理上沒有刪除,deltastore儲存的是被刪除的資料行的ID列表。
deltastore用於進行增量儲存,該操作在後臺進行,對程式設計師是透明的。SQL Server基於效能的考慮,不會因為刪除或更新少數幾行資料,而去更新columnstore,但是會實時更新deltastore。為了返回正確的查詢結果,聚集的列儲存索引將列儲存和deltastore的查詢結果組合在一起,即把deltastore新增的行新增到結果集中,把deltastore中刪除的行從結果集中刪除,從而得到一個正確的結果。
1,增量行組(Delta Rowgroup)
增量行組是僅與列儲存索引一起使用的聚集B樹索引,它儲存資料行,直到行數量達到閾值(1,048,576行),然後把資料移入列儲存中,從而提高了列儲存的壓縮和效能。
當增量行組達到最大行數時,它將從“開啟”狀態轉換為“關閉”狀態。一個名為元組移動器(tuple-mover)的後臺程序會定時檢查封閉行組。如果該程序找到一個封閉的行組,那麼它將壓縮增量行組,並將其作為COMPRESSED行組儲存到列儲存中。
在壓縮增量行組後,現有的增量行組將轉換為TOMBSTONE狀態,然後在無引用的情況下由元組移動器刪除。
2,增量儲存(deltastore)
列儲存索引的每個行組都可以具有一個增量行組,所有的增量行組統稱為增量儲存。
在大批量載入資料的期間,大多數行直接進入列儲存,而無需通過增量儲存。在批量載入結束時,或者執行INSERt操作時,由於插入行的數量太少,無法滿足列儲存的最小大小(102,400行),這些少量的資料行將進入增量儲存,而不是列儲存。 對於行數少於102,400的小型批量負載,所有行均直接進入deltastore。
3,非聚集列儲存索引
非叢集列儲存索引和叢集列儲存索引的功能相同,區別在於,非聚集索引是在行儲存表上建立的輔助索引,而聚集列儲存索引是整個表的主儲存。非聚集索引包含基礎表中部分或全部行和列的副本,索引被定義為表的一列或多列,並具有過濾行的可選條件。
三,列儲存索引的更新
少量的資料載入和插入會直接進入deltastore,當deltastore中的資料行超過102,400行時,後臺程序tuple-mover會把資料更新到columnstore中。
1,少量的資料載入和插入會直接進入deltastore
列儲存索引不是實時更新的,它通過緩衝區deltastore來臨時儲存資料,這樣做的目的是避免頻繁更新,以提高效能。首先,只有當資料的更新數量超過閾值102,400行時,才會觸發列儲存索引的更新。
列儲存索引一次將至少102,400行壓縮到列儲存索引中,從而提高了列儲存壓縮和查詢的效能。要以批量方式壓縮資料行,columnstore索引會累積少量載入(bulk)和插入,並把資料插入到deltastore中。增量儲存操作在後臺進行,為了返回正確的查詢結果,聚集列儲存索引將列儲存和增量儲存中的查詢結果組合在一起。
當行到達時,它們會進入增量儲存區:
- 插入INSERT INTO ... VALUES語句。
- 批量載入結束時,它們的數量少於102,400行。
- 更新,每次更新都實現為刪除和插入。
增量儲存區還儲存已刪除行的ID列表,這些行已被標記為已刪除但尚未從列儲存中實際刪除。
2,把deltastore中資料更新到columnstore中
每一個delta rowgroup最多儲存1,048,576行,當delta rowgroup儲存的資料行達到該閾值時,delta rowgroup的狀態由OPEN轉換為CLOSED,一個名為元組移動器(tuple-mover)的後臺程序檢查封閉行組。如果該程序找到一個封閉的行組,則將壓縮該行組並把其儲存到列儲存中。壓縮增量行組後,現有的增量行組將轉換為TOMBSTONE狀態,隨後在無引用的情況下由元組移動器刪除,並將新的壓縮行組標記為COMPRESSED狀態。
您可以使用ALTER INDEX重建或重新組織索引,以將增量行組強制進入列儲存。請注意,如果在壓縮過程中存在記憶體壓力,則列儲存索引可能會減少壓縮的行組中的行數。
四,執行模式
SQL Server資料庫引擎使用兩種不同的處理模式來處理Transact-SQL語句:
- 行模式執行(Row mode execution)
- 批模式執行(Batch mode execution)
1,行模式執行
行模式執行是與傳統資料表一起使用的查詢處理模式,其中資料以行格式儲存。SQL Server 引擎讀取所需行或索引的所有列,SQL Server從讀取的每一行中,檢索SELECT語句,JOIN謂詞或篩選器謂詞所引用的結果集所需的列。這種執行模式,會把所需行的所有列都讀取出來,即使有些列是不需要的。這種執行模式特別對於查詢少量資料特別有效。
2,批模式執行
批處理模式執行用於同時處理多行,因此稱為批處理。批處理中的每一列都作為向量儲存在單獨的記憶體區域中,因此批處理模式處理基於向量。批處理模式還使用針對多核CPU優化的演算法,並提高了現代硬體上的記憶體吞吐量。
批處理模式執行與列儲存儲存格式緊密整合並進行了優化,批處理模式在可能的情況下對壓縮資料進行操作,從而消除了行模式執行所使用的交換運算子,因此,獲得了更好的並行性和更快的效能。
當以批處理方式執行查詢並訪問列儲存索引中的資料時,SQL Server 引擎會在列段中同時讀取多行,但是SQL Server僅讀取結果所需的列,這些列由SELECT語句,JOIN謂詞或過濾器謂詞引用。
五,列儲存索引的優勢
列儲存索引能夠實現更高級別的資料壓縮,通常是10倍於普通的資料壓縮,以顯著境地資料倉庫的儲存成本。對於資料分析,列儲存索引提供的查詢效能比B-Tree索引快一個數量級。因此,列儲存索引是資料倉庫中用於資料儲存和資料分析的首選方案。
總體來說,對列儲存索引進行查詢,能夠獲得高效率的原因主要是:
- 列儲存的值來自相同的值域或範疇,通常具有很多高度相似的值,這使得資料壓縮的效率非常高。進而減少了資料的儲存和讀取,最小化或消除了系統的I / O瓶頸,並顯著減少了記憶體佔用。
- 高壓縮率通過使用較小的記憶體佔用空間來提高查詢效能,由於SQL Server可以在記憶體中執行更多查詢和資料操作,因此查詢效能可以提高。
- 批處理執行模式在同一時刻會處理多行資料,通常將查詢效能提高2到4倍。
- 查詢語句通常僅從表中選擇少量的幾列,相比行儲存,從表中讀取所有列,列儲存的格式減少了硬碟的總I / O。
參考文件:
Columnstore indexes: Over