SQL Server 2014 聚集列存储
SQL Server 自2012以来引入了列存储的概念,至今2016对列存储的支持已经是非常友好了。由于我这边线上环境主要是2014,所以本文是以2014为基础的SQL Server 的列存储的介绍。下面我们主要看一下列存储的发展以及一些原理:
列存储的开发是想要处理超大量数据进行分析计算,于是在SQL Server 2012时,SQL Server 引入了列存储索引,用以显著提供高传统数据仓库类型语句的性能,并在SQL Server 2014中做了进一步加强。列存储会将一个列的数据单独存放在一起,所以主要会有以下两个优点。
1:同一个列中的数据的相似性比较高,因此压缩比例会更高。磁盘操作时,磁盘的IO也会相应的降低。当然,当压缩的数据读取到内存后解压会需要额外的CPU。
2:由于数据是按照列进行存储和读取的,因此如果某些列在访问中并不需要,那么实际的操作时也会不访问这些列,那么磁盘IO会进一步降低。
3:由于数据是按照列进行存储和读取的,大批量的数据聚合访问等会较以往的行存储更快。
对于列存储来说,主要来说就是数据仓库这个使用场景了,微软最近几年也是在这个方面频频发力。对于数据仓库来说,CPU,内存,磁盘都可能称为性能的瓶颈,但是我们指导磁盘的操作来说相比内存和CPU性能是最慢的,而列存储恰恰是对IO的性能提升是很大的,列存储会减少磁盘的IO操作,提升运算的效率,特别是大量数据的聚合。当然如果是一些线上的精确查找等操作,列存储并不是最好的选择。
对于这些性能的提升和存储 空间的优化,主要是和列存储的实现原理是分不开的(由于非聚集列存储的功能比较鸡肋,我们就不介绍了,因为有非聚集列存储的表成为了一个只读表):
1:Clustered columnstore inde – 整个表都按照列存储进行组织,直接替代了传统的堆表或者聚集索引,可以自由的进行增删改操作。
2:聚集列存储索引虽然相对于非聚集列存储索引在column store这块组织架构基本一样,但是它可以进行增删改操作。原因是它多了一块或者多块行存储部分,这部分称之为delta tore。

原理大概看完之后,下面给出SQL Server2014对列存储的改进:
● 支持数据的读和写
● 在打破了数据只读的限制后,列存储索引使用的范围和场景大大增加
● 相比传统的ad-hoc的增删改操作,在SQL Server2014还是推荐使用bulk insert和分区交换来进行大批次数据的更新,效率更高,维护成本也会降低
● 支持更多的数据类型
● 添加了更多的数据类型支持:(n)varchar(max), varbinary(max), XML, Spatial, CLR
● 基本说来,SQL Server2014的列存储支持所有的non-blob数据类型
● 整个表可建立并且只能建立一个聚集列存储索引。传统的行存储会需要非聚集索引帮助提高访问效率,但是列存储无需这样。并且由于只有一份数据,因此存储需要的磁盘空间大大降低
● 非聚集列索引仍然支持,并且还是只读的结构。
当我们有了聚集列存储索引后,就不需要非聚集列索引了,因为此时所有的数据都是按照列存储了。但是如果表上需要添加Constraints或者工作负载仍然需要B-tree形式的非聚集索引,那么我们还是只能考虑使用非聚集列存储索引。
● 语句的执行上有以下改进
○ 基于矢量的计算方式得到改
○ 支持更多的语法
■ 所有的join方式(包括OUTER, HASH, SEMI (NOT IN, IN)
■ UNION ALL
■ Scalar aggregates
■ “Mixed mode” plans
● 对bitmap和spill操作有进一步的改进
● 对hash join有所改进
其实我在SQL Server 2014列存储的实践当中,还发现有几个不是非常友好的地方
1:SQL Server 2014聚集列存储并不支持视图功能,这个还是比较坑的,因为列存储的主要应用场景就是数据仓库,有很多视图来说要提供报表或者提供给报表部门查询权限,通过视图能够隐藏很多敏感信息,而不支持视图就会很难做决定来具体修改为列存储了
2:SQL Server 2014聚集列存储并不支持alwayson从库的查询
3:SQL Server 2014 12.0.2版本对列存储有漏洞,alwayson日志同步的时候容易造成内部锁争用,影响主从的同步,这点功能我们可能要升级SP1补丁才能解决,我这边从库升级后至今没有出现这个问题,这也是SQL Server 2014列存储的一个BUG吧
以上也算是在生产环境走过的坑,因为考虑不是很周全走了不少路。希望大家能够引以为戒。除了以上几个坑以外,列存储还不支持以下的功能:
在列存储索引中不可使用以下数据类型:
binary(n)、varbinary(n)(在2014及更高版本中允许使用,但不包括varbinary(max)),image、text、ntext、varchar(max)、nvarchar(max),sql_variant,xml
只能通过删除及创建索引的方式重建索引,而不可使用ALTER INDEX命令
在视图或索引视图中无法使用列存储索引
列存储索引无法结合使用以下特性:分发,变更数据捕获,变更追踪,Filestream
列存储索引不可包含多于1024个列
对应的表不可包含唯一性约束、主键约束或外键约束
接下来我们看一下列存储的一些实践:
1:创建列存储的表
CREATE TABLE maxiangqian(
id [int] NOT NULL,
age [int] NOT NULL,
sex [tinyint] NOT NULL,
name varchar(20));
GO
CREATE CLUSTERED COLUMNSTORE INDEX cci_Simple ON maxiangqian;
GO :
2:行聚集索引转换为列存储:
CREATE TABLE maxiangqian(
id [int] NOT NULL,
age [int] NOT NULL,
sex [tinyint] NOT NULL,
name varchar(20));
GO
CREATE CLUSTERED INDEX cl_simple ON maxiangqian (id);
GO
CREATE CLUSTERED COLUMNSTORE INDEX cl_simple ON maxiangqian
WITH (DROP_EXISTING = ON);
或者说我们也可以直接删除聚集索引,然后再
CREATE CLUSTERED COLUMNSTORE INDEX cl_simple ON maxiangqian
效果是一样一样的。
3 将一个堆表转化为列存储表:
第一步就是删除堆表现有的索引,然后创建聚集列存储索引:
CREATE TABLE maxiangqian(
id [int] NOT NULL,
age [int] NOT NULL,
sex [tinyint] NOT NULL,
name varchar(20));
GO
create index pid on maxiagnqian(id) drop index pid on maxiangqian CREATE CLUSTERED COLUMNSTORE INDEX cci_Simple ON maxiangqian;
GO :
上面基本上已经满足你建立列存储的一些功能,下面我们看一下怎么把一个聚集列存储的表转化为普通表:
CREATE CLUSTERED INDEX pid ON maxiangqian
WITH ( DROP EXISTING = ON );
或者
DROP INDEX cci_Simple ON MyFactTable;
OK,我们基本上已经可以知道怎么创建列存储索引了
但是我们指导由于列存储删除的时候只是标记,所以说列存储如果经常更新删除,碎片还是会很大的,下面我们看下怎么消除碎片---重建:
CREATE CLUSTERED COLUMNSTORE INDEX cci_Simple ON maxiagnqian
WITH ( DROP_EXISTING = ON ); ALTER INDEX cci_Simple ON maxiangqian REBUILD PARTITION = ALL
WITH ( DROP_EXISTING = ON );
以上两种方式是都可以实现的。
其实对于列存储来说,卧铺,我这边给我比较大的惊喜就是磁盘空间的节约,列存储的压缩比例可以达到10:1甚至15:1,而且相对来说对于我数据仓库一些大批量的聚合操作性能提升。在节省空间又提高性能的情况下,你还有什么理由不选用列存储呢。
SQL Server 2014 聚集列存储的更多相关文章
- SQL Server 2014聚集列存储索引
转发请注明引用和原文博客(http://www.cnblogs.com/wenBlog) 简介 之前已经写过两篇介绍列存储索引的文章,但是只有非聚集列存储索引,今天再来简单介绍一下聚集的列存储索引,也 ...
- SQL Server 2016 —— 聚集列存储索引的功能增强
作者 Jonathan Allen,译者 邵思华 发布于 2015年6月14日 聚集列存储索引(CC Index)是SQL Server 2014中两大最引 ...
- 在SQL Server 2014里可更新的列存储索引 (Updateable Column Store Indexes)
传统的关系数据库服务引擎往往并不是对超大量数据进行分析计算的最佳平台,为此,SQL Server中开发了分析服务引擎去对大笔数据进行分析计算.当然,对于数据的存放平台SQL Server数据库引擎而言 ...
- 解读SQL Server 2014可更新列存储索引——存储机制
概述 SQL Server 2014被号称是微软数据库的一个革命性版本,其性能的提升的幅度是有史以来之最. 可更新的列存储索引作为SQL Server 2014的一个关键功能之一,在提升数据库的查询性 ...
- SQL Server 2014新特性探秘(3)-可更新列存储聚集索引
简介 列存储索引其实在在SQL Server 2012中就已经存在,但SQL Server 2012中只允许建立非聚集列索引,这意味着列索引是在原有的行存储索引之上的引用了底层的数据,因此会 ...
- 在SQL Server 2014里,如何用资源调控器压制你的存储?
在今天的文章里,我想谈下SQL Server 2014里非常酷的提升:现在你终于可以根据需要的IOPS来压制查询!资源调控器(Resource Governor)自SQL Server 2008起引入 ...
- SQL Server 深入解析索引存储(非聚集索引)
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/非聚集索引 概述 非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非 ...
- SQL Server 2014,表变量上的非聚集索引
从Paul White的推特上看到,在SQL Server 2014里,对于表变量(Table Variables),它是支持非唯一聚集索引(Non-Unique Clustered Indexes) ...
- 谈谈我的微软特约稿:《SQL Server 2014 新特性:IO资源调控》
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 撰写经历(Experience) 特约稿正文(Content-body) 第一部分:生活中资源 ...
随机推荐
- 详解exif.js,应用于canvas照片倒转(海报H5)
业务背景,苹果手机调用上传接口拍照没有问题但是上传到网页上照片倒转了解决方法利用exif.js读取图片参数并对图片进行元数据修改 window.btoa(str)转码 window.atob(base ...
- Java_方法的基本语法格式
[修饰符] 返回值类型 方法名称([参数列表]){ 方法体 } [ ]中的内容是可有可无的 暂时将方法的修饰符编写为 public static 返回值类型有两种情况 : 第一种:无返回值类型,也就是 ...
- RESTful简单介绍
1 什么是restful Restful就是一个资源定位及资源操作的风格.不是标准也不是协议,只是一种风格.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. 资源:互联网所有的事物都 ...
- 使用kerl安装erlang遇到的问题及解决办法-bak
1 需要安装相关包 -dev autoconf 2 出现下面错误 * documentation : * xsltproc is missing. * fop is missing. * xmllin ...
- Unity Github 项目收集
http://gad.qq.com/article/detail/24048 重磅推荐: Github 热门 Unity Assets 查询:http://unitylist.com/browse 最 ...
- 从零开始制作H5人脸融合小游戏
去年的建军节,一个展示军装照的H5人脸融合游戏火遍朋友圈,带来很好的传播效果.最近欧冠决赛要来了,公司决定做一个寻找和你最像的欧冠球星的H5游戏,那么该怎么做呢?认真分析了一下,这个游戏其实用到的技术 ...
- sqlserver 自增ID插入指定数据(转)
set identity_insert 表名 ON --允许对自增列Id插入指定数据 insert into table_name(Id,Name) values(1,'test') set iden ...
- 一:SpringIOC&DI
一:spring 1.spring介绍 spring负责管理项目中的所有对象,看作是项目中对象的管家. spring一站式框架: spring框架性质是属于容器性质的 容器中装什么对象就有什么功能,所 ...
- aspose words做插入压缩后图片到Word文档中
最近用aspose words做导出Word的功能,发现图片的导出有点难受,一开始是这样写的 Document doc = new Document("D:\\Template.docx&q ...
- python os.popen 乱码问题
os.popen('ipconfig') 命令返回的结果在调试时乱码了: output1 = os.popen('ipconfig') o1=output1.read() 我猜这里输出的内容要和控制台 ...