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 操作(例如插入、更新和删除)进行更新。
- 可以与表中的其他索引结合使用。
- 可配置为使用列存储或列存储存档压缩。
- 不以排序方式物理存储列。 相反,它存储数据以改进压缩和性能。 在创建列存储索引之前对数据预先进行排序不是必需的,但这样做可以改进列存储压缩。
在 SQL Server 2014中,聚集列存储索引:
- 在 Enterprise Edition、Developer Edition 和 Evaluation Edition 中提供。
- 可更新。
- 是针对整个表的主要存储方法。
- 没有键列。所有列均为包含列。
- 是表的唯一索引。不能与任何其他索引组合使用。
- 可配置为使用列存储或列存储存档压缩。
- 不以排序方式物理存储列。相反,它存储数据以改进压缩和性能。
以下要点需要注意:
- 在SQL Server 2014中,用户仍然可以像在SQL Server 2012中那样创建一个非聚簇列存储索引,但是这个非聚簇列存储索引是只读查询,无法更新。只有聚簇列存储索引才可以更新。
- 创建用户可以在企业版、开发者版和评估版本中创建聚簇列存储索引,一旦创建就不能有任何形式的非聚簇索引、唯一约束、主键约束和外键约束。
- 如果表中有一个非聚簇列存储索引,用户可以创建唯一约束、主键约束和外键约束,但约束不包括在非聚簇列存储索引中。
- 要改变非聚簇列存储索引的定义,用户必须删除并重新创建非聚簇列存储索引取代旧索引,不适用ALTER INDEX语句。但是可以使用ALTER INDEX禁用和重建列存储索引。
- 当用户创建非聚簇列存储索引时,不能包括稀疏列,也不能使用INCLUDE、ASC、 DESC语句。
- 当用户创建聚簇列存储索引时,索引本身包含数据;而在非聚簇存储索引的情况下,需要辅助存储器存储非聚簇列存储索引中列的副本。
- 聚簇列存储索引(唯一索引)不能与其他索引结合,而在非聚簇列存储索引的情况下,表中可以创建其他索引。
SQL Server 列存储技术的主要特征
- 分列数据格式–每次对一个列的数据进行分组和存储。SQL Server 查询处理可以利用新的数据布局,并显著改进查询执行时间。
- 加快查询结果–列存储索引由于以下原因而可更快地生成结果:
- 只须读取需要的列。因此,从磁盘读到内存中、然后从内存移到处理器缓存中的数据量减少了。
- 列经过了高度压缩。这将减少必须读取和移动的字节数。
- 大多数查询并不会涉及表中的所有列。 因此,许多列从不会进入内存。 这一点与出色的压缩方法相结合,可改善缓冲池使用率,从而减少总 I/O。
- 高级查询执行技术以简化的方法处理列块(称为“批处理”),从而减少 CPU 使用率。
- 键列–列存储索引中没有键列的概念,因此,索引中的键列数限制 (16) 不适应于列存储索引。
- 聚集索引键–如果基表为聚集索引,则聚集键中的所有列必须出现在非聚集列存储索引中。 如果在 CREATE INDEX 语句中未列出聚集键中的某列,该列将自动添加到列存储索引中。
- 分区–列存储索引使用表分区。 无需对表分区语法进行更改。 针对分区表的列存储索引必须与基表实现分区对齐。 因此,如果分区列为列存储索引中的一列,则非聚集列存储索引只能在已分区表上创建。
- 记录大小–索引键记录大小限制(900 字节)也不适应于列存储索引。
- 查询处理–除列存储索引之外,SQL Server 还引入批处理以利用数据的分列方向。 列存储结构和批处理都会提升性能,但考察性能问题时远不止考虑其中一个因素那么简单。
- 表无法更新–对于 SQL Server 2012,无法更新具有列存储索引的表。
列存储索引的限制
- 包含的列数不能超过 1024。
- 无法聚集。 只有非聚集列存储索引才可用。
- 不能是唯一索引。
- 不能基于视图或索引视图创建。
- 不能包含稀疏列。
- 不能作为主键或外键。
- 不能使用 ALTER INDEX 语句更改。 而应在删除后重新创建列存储索引。 (您可以使用 ALTER INDEX 禁用和重新生成列存储索引。)
- 不能使用 INCLUDE 关键字创建。
- 不能包括用来对索引排序的 ASC 或 DESC 关键字。 根据压缩算法对列存储索引排序。 不允许在索引中进行排序。 可能按照搜索算法对从列存储索引中选择的值进行排序,但是您必须使用 ORDER BY 子句来确保对结果集进行排序。
- 不以传统索引的方式使用或保留统计信息。
参考文档: