SQL Server 的列存储索引是SQL Server 2012 release版本新增的内容,用于提高数据仓库的查询性能,本篇文章阐述列存储的性能调优。
列存储索引性能的基本原则
在相同的硬盘和数据量时,列存储能够明显提高部分查询的速度。致使列存储查询效率高的因素有以下几点:
1. 列存储索引采用高度压缩的形式来存储数据,并且每一列都存储到不同的页分组上。由于数据仓库中的大部分表包含30列以上,但是一般的查询可能只需要5、6列,并且仅查询展示的列需要从磁盘中读取,这样,采用列存储会大大的减少数据仓库的查询I/O。对于查询频繁的列在内存中会进行缓存,包含数据备份的聚集B-树或堆经常用来构建列索引和执行大部分的查询。在查询的周期内,他会定期的释放内存空间和资源。
2. 批处理 是一种更高效、基于矢量查询并且运用列存储索引的方法。一批是包含1000行的一个集合。相比于基于行的旧查询方式,批处理能够降低7%-40%的cup消耗。有效的矢量运算允许批处理降低基本过滤、表达式预估、执行计划、联合查询的CPU花费。
3. 块分割能够跳过大部分数据来加快数据扫描。在列存储索引里的每一部分达到1000行会单独分割成一块,每一块都有存储着该块内每一列最大值、最小值的元数据。存储引擎通过元数据来检测过滤条件。如果引擎检测到块内没有符合要求的数据,那么它会跳过该块数据,并且这块数据不会进行磁盘的读写。
4. 存储引擎能够在查询之前去除部分数据,这样能够提高查询的响应速度。
SQL Server 已经完善了列存储索引和批处理查询这种模式。一个部分查询可以执行为一个批处理查询模式,一个标准行查询模式或者一个混合了批处理和标准行查询模式。获取最佳性能的关键是确认查询流程的大部分数据是在批处理模式。即使大批的查询不能在批处理模式下执行,使用列存储索引也能通过减少磁盘I/O,存储引擎的预过滤来获得重要的性能提升。
通过界面上的【显示执行计划】,将鼠标放到消耗昂贵的扫描操作上,查看提示。它会显示预估和实际执行模式是行模式或者批处理模式。
什么情况下使用列存储索引
1. 将列存储索引仅应用到大数据量的表上。应将列存储索引创建在数据仓库的实际花费表上,而不是一个定义表。如果你有一个包含至少百万级的数据量的定义表,那么也可以考虑将列存储索引应用到这个定义表上。
2. 用列存储索引包含表的每一列。如果不这样做,查询不在列存储索引中的列将不会享受列存储索引带来的效率。
3. 结构化查询,避免关联两个或更多个大表,通过一个大的实际花费表关联多个小的定义表来提高效率。
什么情况下不建议使用列存储索引
1. 避免直接的在列存储索引的列上进行字符串过滤和通过字符串列进行表的关联。对字符串过滤不能使用列索引进行扫面,关联字段为字符串不如使用数值类型关联更有效率。对数值类型和时间类型的过滤都可以使用列存储索引进行扫描,在实际环境的大表中可以考虑使用整形的编码来代替字符串类型,并将字符串类型转移到一个小的定义表,通过整形编码进行关联,这样查询效率会更高。
2. 避免在列存储索引的列上使用外连接(out join),外连接不能应用查询的批量处理,相反的,是通过低版本的行查询进行处理。
3. 避免在列存储索引的列上使用不包含语句(not in),原因同第2条。
4. 避免在列存储索引的列上使用Union All语句来关联其他表。原因同上。
对于以上不建议使用列存储索引的情况,可以通过SQL Server的CTE语句(with....as ) 来进行解决,这样可以是查询使用批量处理的引擎进行处理。
由于英语能力有限,翻译的语句可能存在歧义,如不理解,请阅读原文。