SQL Server新特性:列存儲
列存儲索引是SQL Server 2012中為提高數據查詢的性能而引入的一個新特性,顧名思義,數據以列的方式存儲在頁中,不同于聚集索引、非聚集索引及堆表等以行為單位的方式存儲。因 為它并不要求存儲的列必須唯一,因此它可以通過壓縮將重復的列合并,從而減少查詢時的磁盤IO,提高效率。
SQL Server 內存中列存儲索引通過使用基于列的數據存儲和基于列的查詢處理來存儲和管理數據。 列存儲索引適合于主要執行大容量加載和只讀查詢的數據倉庫工作負荷。 與傳統面向行的存儲方式相比,使用列存儲索引存檔可最多提高 10 倍查詢性能,與使用非壓縮數據大小相比,可提供多達 7 倍數據壓縮率。
為了分析列存儲索引,先看看B樹或堆中的數據的存儲方式,如下圖,在page1上,數據是按照行的方式存儲數據的,假設一行有10列,那么在該頁上,實際的存儲也會以每行10列的方式存儲,如下圖中的C1到C10。
假設我們執行select c1,c2 from table時,數據庫會讀取整個page1,顯然,從C3到C10并不是我們想要的數據,但因為數據庫每次讀的最小單位是一頁,因此這些不得不都加載到內存中。如果數據頁多時,必然要消耗更過的IO和內存。
如果是列存儲索引,數據按列的方式存儲在一個頁面中,如下圖,page1中只存儲表中C1列,page2只存儲c2列,以此類推,page10存儲 c10列。假設我們執行select c1,c2 from table時,結果會怎樣呢?數據庫只會讀page1和page2,至于page3到page10因為沒有對應的數據,數據庫不會去讀這些頁,也不會加載 到內存中,相比行存儲而言,減少了磁盤IO和優化了內存的使用。
列存儲版本
SQL Server 2012、SQL Server 2012 并行數據倉庫和 SQL Server 2014 全都使用列存儲索引來加快常見數據倉庫查詢的執行速度。 SQL Server 2012引入了兩個新功能:非聚集列存儲索引和基于向量的查詢執行功能(處理稱作“批處理”的單元中的數據)。SQL Server 2014 除了具有 SQL Server 2012 中的功能之外,還新增了可更新聚集列存儲索引。
在 SQL Server 2012 中,非聚集列存儲索引:
- 可對聚集索引或堆中列的子集建立索引。 例如,它可以對常用列建立索引。
- 需要附加的存儲空間以存儲索引中列的副本。
- 通過重新生成索引或者切入和切出分區進行更新。不可以使用 DML 操作(例如插入、更新和刪除)進行更新。
- 可以與表中的其他索引結合使用。
- 可配置為使用列存儲或列存儲存檔壓縮。
- 不以排序方式物理存儲列。 相反,它存儲數據以改進壓縮和性能。 在創建列存儲索引之前對數據預先進行排序不是必需的,但這樣做可以改進列存儲壓縮。 </ul>
- 在 Enterprise Edition、Developer Edition 和 Evaluation Edition 中提供。
- 可更新。
- 是針對整個表的主要存儲方法。
- 沒有鍵列。所有列均為包含列。
- 是表的唯一索引。不能與任何其他索引組合使用。
- 可配置為使用列存儲或列存儲存檔壓縮。
- 不以排序方式物理存儲列。相反,它存儲數據以改進壓縮和性能。 </ul>
- 在SQL Server 2014中,用戶仍然可以像在SQL Server 2012中那樣創建一個非聚簇列存儲索引,但是這個非聚簇列存儲索引是只讀查詢,無法更新。只有聚簇列存儲索引才可以更新。
- 創建用戶可以在企業版、開發者版和評估版本中創建聚簇列存儲索引,一旦創建就不能有任何形式的非聚簇索引、唯一約束、主鍵約束和外鍵約束。
- 如果表中有一個非聚簇列存儲索引,用戶可以創建唯一約束、主鍵約束和外鍵約束,但約束不包括在非聚簇列存儲索引中。
- 要改變非聚簇列存儲索引的定義,用戶必須刪除并重新創建非聚簇列存儲索引取代舊索引,不適用ALTER INDEX語句。但是可以使用ALTER INDEX禁用和重建列存儲索引。
- 當用戶創建非聚簇列存儲索引時,不能包括稀疏列,也不能使用INCLUDE、ASC、 DESC語句。
- 當用戶創建聚簇列存儲索引時,索引本身包含數據;而在非聚簇存儲索引的情況下,需要輔助存儲器存儲非聚簇列存儲索引中列的副本。
- 聚簇列存儲索引(唯一索引)不能與其他索引結合,而在非聚簇列存儲索引的情況下,表中可以創建其他索引。 </ol>
- 分列數據格式–每次對一個列的數據進行分組和存儲。SQL Server 查詢處理可以利用新的數據布局,并顯著改進查詢執行時間。
- 加快查詢結果–列存儲索引由于以下原因而可更快地生成結果:
- 只須讀取需要的列。因此,從磁盤讀到內存中、然后從內存移到處理器緩存中的數據量減少了。
- 列經過了高度壓縮。這將減少必須讀取和移動的字節數。
- 大多數查詢并不會涉及表中的所有列。 因此,許多列從不會進入內存。 這一點與出色的壓縮方法相結合,可改善緩沖池使用率,從而減少總 I/O。
- 高級查詢執行技術以簡化的方法處理列塊(稱為“批處理”),從而減少 CPU 使用率。 </ul> </li>
- 鍵列–列存儲索引中沒有鍵列的概念,因此,索引中的鍵列數限制 (16) 不適應于列存儲索引。
- 聚集索引鍵–如果基表為聚集索引,則聚集鍵中的所有列必須出現在非聚集列存儲索引中。 如果在 CREATE INDEX 語句中未列出聚集鍵中的某列,該列將自動添加到列存儲索引中。
- 分區–列存儲索引使用表分區。 無需對表分區語法進行更改。 針對分區表的列存儲索引必須與基表實現分區對齊。 因此,如果分區列為列存儲索引中的一列,則非聚集列存儲索引只能在已分區表上創建。
- 記錄大小–索引鍵記錄大小限制(900 字節)也不適應于列存儲索引。
- 查詢處理–除列存儲索引之外,SQL Server 還引入批處理以利用數據的分列方向。 列存儲結構和批處理都會提升性能,但考察性能問題時遠不止考慮其中一個因素那么簡單。
- 表無法更新–對于 SQL Server 2012,無法更新具有列存儲索引的表。 </ul>
- 包含的列數不能超過 1024。
- 無法聚集。 只有非聚集列存儲索引才可用。
- 不能是唯一索引。
- 不能基于視圖或索引視圖創建。
- 不能包含稀疏列。
- 不能作為主鍵或外鍵。
- 不能使用 ALTER INDEX 語句更改。 而應在刪除后重新創建列存儲索引。 (您可以使用 ALTER INDEX 禁用和重新生成列存儲索引。)
- 不能使用 INCLUDE 關鍵字創建。
- 不能包括用來對索引排序的 ASC 或 DESC 關鍵字。 根據壓縮算法對列存儲索引排序。 不允許在索引中進行排序。 可能按照搜索算法對從列存儲索引中選擇的值進行排序,但是您必須使用 ORDER BY 子句來確保對結果集進行排序。
- 不以傳統索引的方式使用或保留統計信息。 </ol>
列存儲索引的限制
參考文檔:
在 SQL Server 2014中,聚集列存儲索引:
以下要點需要注意:
SQL Server 列存儲技術的主要特征