以前已经写过两篇介绍列存储索引的文章,可是只有非汇集列存储索引,今天再来简单介绍一下汇集的列存储索引,也就是可更新列存储索引。在SQL Server 2012中首次引入了基于列存储数据格式的存储方式。叫作“列存储索引”。前一篇我已经比较了行存储索引与非汇集的列存储索引(http://www.cnblogs.com/wenBlog/p/5682024.html)。其中对于在小表的指定值或者小范围的查询来说,尤为针对事务性的负载行存储是很合适的。可是对于分析性负载像数据仓库和BI,在查询中将会对大量数据进行全扫描,例如事实表,这时候列存储索引就是更好地选择。html
在列存储索引中,数据按照独立列组织到一块儿造成索引结构。每列都数据都位于被高度压缩的数据集中,叫作数据段。这个数据段只包含该列的值,对于大型表它分到多个数据段中,每一个数据段中只含有100万行数据,这就叫作行组、数据段由一个或者多个数据页组成。数据将在内存和硬盘上以数据段的形式传输。sql
这种索引提升了数据仓库的查询效率。这种经过压缩得到数据格式要比B-Tree结构的压缩率高7倍多。同时因为列存储索引使用了批处理模式执行,数据处理也是批处理的,较少了CPU的使用。列存储索引强化了检索数据的速度,与行存储不一样的是不用查询全部列。由于这个缘由,更少数据被读取到内存中,再处处理器缓存处理。相关的这些因素都会减小硬盘IO,提升总体查询的性能。数据库
在2014中列存储索引有如下限制:缓存
最多支持1024列在你的索引中;性能优化
列存储索引不能被定义为惟一性索引;ide
不能建立视图;性能
不能包含稀疏列;测试
不能使用ALTER INDEX来修改索引,只能drop而后从新建立;大数据
不能使用INCLUDE关键字。优化
不能排序列;
不能使用FILESTREAM属性。
固然还有一些数据类型不能包含在列存储索引中(binary , varbinary , ntext , text, , image, varchar(max) , nvarchar(max), uniqueidentifier, rowversion , sql_variant,精度大于18 的decimal,CLR 和xml等)
另外一方面,对于索引列900字节的限制也不适用与列存储索引。
在SQL Server2012 中,只能建立非汇集列存储索引,而且不能更新。为了更新你必须删除索引,而后进行插入、更新或者删除的操做后在重建索引。
在2014中列存储索引获得了不小的提高,好比消除了只读限制。增长了汇集列存储索引,列存储索引做为了表的存储方式,存储表的数据。
区别 |
汇集列存储索引 |
非汇集列存储索引 |
索引列 | 须要指定列上建立 | 全部列都包含在内 |
存储 | 额外增长百分之10的空间做为索引 | 压缩十倍的数据量,若是表以前是页压缩,则能够压缩5倍左右 |
更新 | 是 | 否 |
排序 | 在建立以前进行排序 | 否 |
如图增量存储部分咱们叫作deltastore,用于存储不够最小行组大小的数据。流程就是将行数据提取成列数据,而后进行压缩存储,多余的部分放到deltastore中。
插入新行的时候,值被存储在deltastore中,直到达到最小rowgroup(行组)大小时,而后压缩并移动到列存储数据段中。
删除数据时,行将被删除从deltastore存储中,可是在列存储索引数据段中只是被标记为删除,除非重建后才会被真的删除。
更新的时候,在deltastore存储中行数据被删除,而后在列存储数据段中被标记为删除,新的列别插入到deltastore中。
最后当重建索引的时。SQLServer将会删除全部标记为删除的数据段,数据存储在deltastore中的将与数据段中的数据合并,而后进行压缩。
咱们首先建立一个事实表在数据库中脚本以下:
1 USE SQLShackDemo 2 3 GO 4 --建立表 5 CREATE TABLE [dbo].[FactFinance]( 6 7 [FinanceKey] [int] NOT NULL, 8 9 [DateKey] [int] NOT NULL, 10 11 [OrganizationKey] [int] NOT NULL, 12 13 [DepartmentGroupKey] [int] NOT NULL, 14 15 [ScenarioKey] [int] NOT NULL, 16 17 [AccountKey] [int] NOT NULL, 18 19 [Amount] [float] NOT NULL, 20 21 [Date] [datetime] NULL 22 23 ) ON [PRIMARY] 24 25 GO 26 27 --建立汇集索引: 28 29 CREATE CLUSTERED INDEX [IX_FactFinance_FinanceKey_DateKey] ON [dbo].[FactFinance] ( [FinanceKey],[DateKey]) 30 GO 31 32 33 --查询表: 34 35 SELECT [FinanceKey] 36 37 ,[DateKey] 38 39 ,[OrganizationKey] 40 41 ,[DepartmentGroupKey] 42 43 FROM [FactFinance]
让咱们检查下汇集索引扫描操做符,Estimated I/O Cost(估计IO花销) 的值为0.183866,Estimated CPU Cost(估计CPU花销)为0.0435069,为了比较列索引的值,咱们先记住:
如今咱们建立列存储索引在非汇集索引:
CREATE NONCLUSTERED COLUMNSTORE INDEX [IX_FactFinance_FinanceKey_DateKey_OrganizationKey_DepartmentGroupKey] ON [FactFinance] ([FinanceKey],[DateKey],[OrganizationKey],[DepartmentGroupKey]) GO SELECT [FinanceKey] ,[DateKey] ,[OrganizationKey] ,[DepartmentGroupKey] FROM [FactFinance]
这个列存储索引扫描操做符以下所示:
如上所示,Estimated I/O Cost从0.183866降低到0.0112731,这是由于SQL引擎只检索须要的列,节省了IO和内存资源。Estimated CPU的时间没有变化。
IO强化与以前相比是明显的,咱们也能够比较两个查询,启用I/O statistics,检查IO的hits 表现以下:
SET STATISTICS IO ON GO SELECT [FinanceKey] ,[DateKey] ,[OrganizationKey] ,[DepartmentGroupKey] FROM [FactFinance] with (index (IX_FactFinance_FinanceKey_DateKey)) GO SELECT [FinanceKey] ,[DateKey] ,[OrganizationKey] ,[DepartmentGroupKey] FROM [FactFinance] with (index(IX_FactFinance_FinanceKey_DateKey_OrganizationKey_DepartmentGroupKey))
正如所示,比较执行计划,使用列存储索引的要比行索引的好四倍,那么指望一下处理大数据时的10倍性能:
当比较逻辑读时你也能发现类似的结果。明显这个逻辑读也是四倍+关系。
那么咱们能够根据下图归纳一下传统的行索引与列存储因此的通常性区别:
也可以使用SSMS建立索引: Indexes -> New Index ->Non-Clustered Columnstore Index 以下:
与非汇集索引建立相似,选择列,而后这些列没有排序也不能使用Include选项:
下图中我在SQL Server2014 企业版中,建立汇集索引:
须要注意的是若是在表上已经有其余索引,尝试建立汇集列存储索引就会出现错误,正如咱们以前说的,同一个表中不能或者其余索引:
不用选择列,全部数据都包含在内了:
若是你有大型的事实表而且存在查询问题的,或者SSAS存在其余性能问题的,列存储是一个不错的方案。一下两种状况是通过测试的比较好的应用场景:
列存储索引是一个使用SQL Server性能优化的方案,经过减小IO消耗,尤为对数据仓库和BI查询都是由明显性能提高。它经过排序数据做为列存储,而后压缩,并使用批处理来处理数据。固然,必需要确保使用列存储索引的使用带来了好处,而不会引发其余性能问题才能使用。好比须要注意使用的硬件环境和数据,若是没有join、过滤、或者聚合导出巨大的数据量没有足够的内存则将被暂时放入硬盘进行switch off,从而引发查询性能降低。尽可能在使用以前在测试环境中测试是否适合使用,同时还要关注其余环节是否受影响。
补充,在2016中增长的几个我认为不错新的feature:
基于汇集列存储索引的 B 树索引;
基于内存优化表的列存储索引;
CREATE TABLE 和 ALTER TABLE 中的列存储索引的压缩延迟选项;
单线程查询的批处理执行。