Columnstored index是SQL Server 2012后加入的重大特性,数据不再以heap或者B Tree的形式存储(row level)存储在每一个数据库文件的页里面,而是以列为单位存储。加上本身数据在存储到磁盘的时候是经过压缩算法压缩过后存储的,对于存储空间有很大的节省。各个特点非常适合数据库仓库型数据库,尤其是星状结构的设计(Dimension + Fact)。
各个版本的特点和差异:
SQL Server 2014
1)聚集列存储索引,可更新,但是不能再创建其他的索引
2)非聚集列存储索引,不可更新,除非Rebuild或者Switch Partition,但是一些操作可以以批处理的形式处理
3)多了一个压缩选项COLUMNSTORE_ARCHIVE,压缩比例更高,对于不常访问的数据(年久远的数据)非常有帮助,节省磁盘和内存空间占用
4)支持更多的操作符使用多线程批处理,包括Sort、Union All、Group By、Scan
5)聚集列存储索引不支持主键和外键
SQL Server 2016:
1)除聚集列存储索引外,还可以再额外创建多个行存储索引
2)非聚集列存储索引可更新,而且可以再创建索引时加filter
3)In-memory table可以创建一条列存储索引
4)聚集列存储索引支持主键和外键
5)增加了COMPRESSION_DELAY选项可以延迟N分钟数据压缩
SQL Server 2014和2016最大的特点是多了数据批载入。
SQL Server 2016在插入数据到列存储索引时采用了与Bulk Insert类似的技术快速插入数据到目标表。
1)数据不经过排序就直接插入到表中
2)102400行数据作为每一个块,为满的就放到deltagoup
列存储的Bulk Load是可以并行的,把不同与行存储Bulk insert的并行需要通过加表锁来锁定整张表,列存储的Bulk insert是不需要加表锁,因为在进行行分组(row groups)的时候就已经对每一个分组都加了排它锁,然后压缩。
列存储也是最小化日志记录,但是行插入到deltastore还是会进行完整的日志记录
对row group加的锁是row group级别的,但是对deltagroup是页或者区级别的
如果单纯是为了把数据加载到一张stage表为后面的数据清洗和转换做准备,那么堆表(heap table)比起聚集列存储索引的表在载入速度上要更快。因为列存储需要对数据进行分组(row group),然后压缩后载入到磁盘。而堆表之所以快是因为第一它的数据是不需要任何排序和分组的(除非有做分区表),也不需要压缩,加上TABLOCK后数据载入最优化。而如果作为临时用的数据,临时表的速度要比堆表要更快。因为临时表是最小的事务日志记载。所以最常见的做法应该是把数据载入到stage表,然后从stage表载入到列存储索引。在载入数据到列存储索引的时候加TABLOCK可以使语句变成多线程处理(SQL Server 2016),加上数据在进入压缩后的列存储行组是最小日志记录的(进入delta group不是最小日志记录)。
下面语句可以把所有的row group都压缩,包括delta group,不管满了没有
ALTER INDEX <index-name> on <table-name> REORGANIZE with (COMPRESS_ALL_ROW_GROUPS = ON)
SQL Server 2016允许在列存储索引上再创建非聚集行索引,这样带来的好处是:
1)增加了对行数据的索引查找能力(index seek)
2)通过唯一索引实现主键的功能
3)数据更新时的锁优化,通过非聚集行索引实现行级别的锁,而对于列存储索引也只是row-group级别的锁
如果想让列存储聚集索引按照某个字段的排序存储,可以先对表的该列创建聚集索引,删除聚集索引,然后对表再创建列存储聚集索引,前提是DOP要设置为1。
Rowgroup elimination是SQL Server 2016的一大特性,可以帮助在查找数据的时候可以根据查询语句的谓语消除非必要的row group的扫描,也就是指扫描需要的row group。SQL Server是通过查找元数据,就是列存储索引的segment的最大和最小值区间来判断是否符合插叙语句的谓语条件来决定是否要扫描该row group的某个列的数据。sys.column_store_segments的min_data_id和max_data_id代表了上面的最大和最小值区间。而sys.column_store_row_groups则记录了表所创建的列存储索引的row group,可以用于判定是否需要rebuild这个索引,因为可能索引中被删除行过多而造成性能较差(借助deleted_rows列和total_rows)。
Batch Mode Execution是SQL Server 2016的另一大特性,对于900行以上的数据集,除了是INSERT\UPDATE\DELETE这种必须是行模式的,以900为单位批次处理数据集。并非所有的操作符都可以使用Batch Mode,三种join里面也只有hash支持,sort和窗口聚合函数也在SQL Server下支持。
参考:
Columnstore Indexes Versioned Feature Summary
Columnstore Indexes Data Loading