<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859838">SQL Server Column Store Indeses</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859839">1. 概述</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859840">2. 索引存儲</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859841">2.1 列式索引存儲</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859842">2.2 資料編碼和壓縮</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859843">2.2.1 編碼</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859844">2.2.2 優化行順序</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859845">2.2.3 壓縮</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859846">2.3 I/O和Cache</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859847">3 查詢處理和優化</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859848">3.1 查詢處理加強</a>
<a href="http://www.cnblogs.com/Amaranthus/p/4294085.html#_Toc411859849">3.2 查詢優化</a>
SQL Server 11增加了新特性列存儲索引和相關的查詢操作符。批量行處理來提高資料倉庫的查詢性能。
傳統的資料庫系統使用行存儲的,heap,btree都是。這種資料組織方式對于,隻處理到一部分資料的事務處理表現很好,但是并不适應資料倉庫的,資料倉庫通常是對掃描很多記錄,但是隻涉及到某一些行。這個時候列方式組織就能執行的很好。因為可以讀取需要的列,并且列存儲的資料可以得到很好的壓縮。
SQL Server列存儲索引是純粹的列存儲,不是混合的。不同的列被存放在不同的page下。
使用1TB測試資料庫(TPC-DS),catalog_sales包含1.44billion條資料,使用星型結構來測試列存儲索引的性能提升,隻對事實表做列存儲索引,其他表都是行存儲。在40核啟用了超線程,256GB記憶體,磁盤性能在10GB/sec裝置上測試。
SELECT w_city ,w_state ,d_year ,SUM(cs_sales_price) AS cs_sales_price
FROM Warehouse ,catalog_sales ,date_dim
WHERE w_warehouse_sk = cs_warehouse_skAND cs_sold_date_sk = d_date_skAND w_state = 'SD'AND d_year = 2002
GROUP BY w_city , w_state ,d_year
ORDER BY d_year , w_state , w_city;
比較容易看出性能,在improvement行中可以看出,CPU花費少了13倍,在cold情況下執行時間少了25倍。
在SQL Server 11之前所有的索引都是以行存儲的。不管是btree還是heap。
列存儲,以新的索引類型引入到SQL Server列存儲索引。設計的目的是為了加快列的掃描。
列存儲儲存方式如下:
1. 把行轉化為column segment,先把行分為一個個的row groups,每個groups由1million資料。每個row group獨立的進行編碼和壓縮。生産一個壓縮的column segment,裡面隻包含一個列。
如圖表分為3個row group,獨立的進行編碼和壓縮,生成9個壓縮的column segments。
2. 然後使用現有的blob存儲機制來儲存這些壓縮的column segments。Segment目錄用來跟蹤每個segment的位置,這樣每個segment可以很容易的被定位。這個segment目錄被儲存在系統表可以使用sys.column_store_segments來檢視,視圖裡面也儲存了一些中繼資料。
資料存儲是使用壓縮的方式來減少存儲空間和I/O消耗。可以選擇允許column segment直接使用不需要解壓縮。壓縮步驟如下:
1.對所有的column的值進行編碼。
2.優化行的順序。
3.對每個行進行壓縮。
編碼就是把列值轉化為唯一的類型:32bit或者64bit。支援2個類型的encode:基于字典的編碼和基于值的編碼。
基于字典的編碼把不同的值轉為連續的int值的集合。存入資料目錄,本質上是存入以dataids為索引的一個數組中。每個資料字典儲存在獨立的blob中,可以使用sys.column_store_dictionaries檢視。
基于值的編碼應用在int或者decimal資料類型上。把某個範圍的值弄小。基于值的編碼由2部分組成:基值和指數。
一旦指數被選中,column segment上的值就會被調整。
重要的性能提升主要是來自于壓縮,資料使用RLE壓縮(run-length encoding)。RLE在許多一樣的資料在一起的時候壓縮表現會很好。因為在row groups中順序是不重要的,是以可以随意的重新組織順序來提高壓縮效率。
我們使用vertipaq算法來重新重新組織row group中的順序,提高RLE的壓縮性能。
一旦row group中的行被重新排序,就可以使用RLE來壓縮。
Blob存儲的column segment或者字典可能跨多個page,當我們讀入記憶體的時候column segment和字典被儲存在新的cache中用來儲存大對象,而不是基于page 的buffer pool中。而且每個對象都是連續的,沒有空隙。
為了提高I/O性能,預讀可以被應用在segment内和多個segment上。對于磁盤存儲,可以使用額外的壓縮,是否使用額外的壓縮,需要在I/O和cpu之間平衡。
标準的查詢處理是基于行的,一次處理一行,為了減少cpu,使用了新的處理方式,以批處理的方式一次性處理一批行。批處理方式适用于OLAP但是不會取代行處理在OLTP中的地位。
SQL Server沒有去建立一個新的引擎,而是在原來的引擎上面做擴充。有以下好處:
1.使用者不需要花時間在新的引擎上,和不需要再2個引擎上做轉化。
2.極大的減少了實作引擎的花費
3.查詢計劃可以混合兩個操作。
4.查詢可以自動的在batch和row操作間轉化。
5.所有的特性相容。
新的batch有獨立的通路方法有不同的資料源支援,列存儲索引的通路方法支援謂詞和bitmap過濾。Batch模式一般适用于資料密集的計算,計算複制的過濾條件,select清單,join和聚合。
新的通路方法有新的優化,如:延遲字元串執行個體化和透明使用新的疊代器。雖然批處理方式可以減少cpu處理時間,但是達不到目标。
有一些額外的優化方式:
1.新的疊代器針對最新的cpu進行優化,增加記憶體的吞吐量。
2.bitmap過濾的實作。
3.runtime資源管理被提升,可以讓操作以更靈活的方式共享。
和其他索引不同,列存儲索引不能很好的支援point query和range scan,因為列存儲索引沒有順序,沒有統計資訊。列存儲索引值提供高壓縮的資料來減少cpu和io,對于scan可以從列存儲索引上提升性能。
是否使用batch處理方式由查詢分析器決定,也可以混合row和batch處理,但是2者之間的轉化是有花費的,是以mssql會限制轉化次數。
為了在生成的圖形計劃中區分batch和row,加入了一個新的屬性,用這個屬性來區分是batch還是row。,也可以決定是否有必要做轉化。所有的batch操作要求輸入都是batch,row操作輸入都是row。
除了batch處理方法,也引入的新的方法來控制多個join。Sql server優化器視圖把inner join轉化為一個多元join操作。好處是可以一次性處理整個join graph。
1.我們先通過join的表達式和謂詞來識别那個join key 是唯一的。使用識别的唯一資訊來判斷哪些是事實表,哪些是次元表,事實表不會有唯一資訊。
2.然後從最小的事實表開始展開join graph,盡量多的覆寫次元表,在事實表周圍形成一個雪花型。然後處理另外一個試試表。
3.之後,我們會有多個雪花型join,然後從最大的事實表開始,遞歸的把周圍的雪花以次元表方式加入,開始形成最終的執行計劃。首先,識别哪些join值得建立bitmap過濾,一旦識别就建立一個right deep join樹,把次元表放在左邊,事實表放在右邊。每個次元表可能都是一個雪花型,然後以遞歸的方式分解每一個雪花。在每個join上,确定條件,檢查是否可以使用batch,如果不行則用row模式。若到達了,所有吧可以batch的放在下面,其他的放在上面。
參考:
<a href="http://research.microsoft.com/apps/pubs/default.aspx?id=156647" target="_blank">SQL Server Column Store Indexes</a>
本文轉自 Fanr_Zh 部落格園部落格,原文連結:http://www.cnblogs.com/Amaranthus/p/4294085.html,如需轉載請自行聯系原作者