列存储索引是好的!对于数据仓库和报表工作量,它们是真正的性能加速器。与聚集列存储结合,你会在常规行存储索引(聚集索引,非聚集索引)上获得巨大的压缩好处。而且创建聚集列存储索引非常简单:

CREATE CLUSTERED COLUMNSTORE INDEX ccsi ON TableName
GO

但这是你对聚集列存储需要知道的一切?并不是,如你在这篇文章会看到的……

什么是列存储段(ColumnStore Segments)?

在我各个研讨会和公共培训课程期间,我经常开玩笑:一旦你开释使用聚集列存储索引,你就不需要知道索引的更多信息。使用聚集列存储索引很太多的优点,它会带来巨大的性能提升:

  • 更好的压缩
  • 批处理模式执行
  • 更少I/O,更好内存管理
  • 段消除

如你从下例子看到的,在SQL Server里创建聚集列存储索引非常简单:

CREATE CLUSTERED COLUMNSTORE INDEX idx_ci ON FactOnlineSales
GO

你只需指定表名,没别的。甚至你不需要担心聚集键列,因为这个概念对列存储索引不适用。很简单,是不是?让我们在适当的地方用刚才的聚集索引运行一个简单的查询:

-- Segment Elimination doesn't work quite well, because
-- we have a lot of overlapping Segments.
SELECT
DateKey,
SUM(SalesAmount)
FROM FactOnlineSales_Temp
WHERE
DateKey >= ''
AND DateKey <= ''
GROUP BY
DateKey
GO

这个查询非常快,因为对于查询执行,SQL Server可以使用聚集列存储索引。从STATISTICS IO输出也向你展示了,对于聚集列存储索引不需要很多LOB Logical Reads

但那些段读取(Segment Read)和段跳过(Segment Skipped)度量呢?

你们也许知道列存储索引内部分成所谓的列存储段(ColumnStore Segments)。一个列存储段通常指定到特定的列和行组。一个行组包含近100万行。下图很好的展示了这个重要概念:

来源:https://www.microsoft.com/en-us/research/publication/enhancements-to-sql-server-column-stores/

什么是列存储段消除(ColumnStore Segment Elimination)?

这里最重要的是,对于每个列存储段,SQL Server内部存储了最小和最大的值。基于这些值,SQL Server可以进行所谓的段消除。段消除意味着SQL Server只读取包含请求数据的那些段(在访问列存储索引时)。你可以认为它是和分区消除一样得方式,在你和分区表打交道的时候。但这里的消除发生在列存储段级别。

如你在刚才的图片所见,在列存储索引访问期间SQL Server不能消除任何段,因为默认情况下,在列存储索引里你没有排列顺序。你数据的排列顺序取决于在执行计划里,在你创建列存储索引时,SQL Server如何读取数据:

如你所见,聚集列存储索引通过从最初包含数据的堆表创建。因此在聚集列存储索引里,你没有排列顺序,因此段消除不能很好为你工作。

如何改善情况?在你的数据里首先通过创建传统的行存储聚集索引来强制排序,然后修改它为聚集列存储索引!偶滴神啊……

-- Now we create a traditional RowStore Clustered Index to sort our
-- table data by the column "DateKey".
CREATE CLUSTERED INDEX idx_ci ON FactOnlineSales_Temp(DateKey)
GO -- "Swap" the Clustered Index through a Clustered ColumnStore Index
CREATE CLUSTERED COLUMNSTORE INDEX idx_ci ON FactOnlineSales_Temp
WITH (DROP_EXISTING = ON)
GO

有了传统的聚集行存储索引就位,当你创建聚集列存储索引时,在执行计划里,查询优化器会引用这个索引:

作为副作用,在聚集列存储索引里,你现在应该有已排序的数据,段消除应该会很好处理:

-- Segment Elimination works better than previously, but still not perfectly.
SELECT
DateKey,
SUM(SalesAmount)
FROM FactOnlineSales_Temp
WHERE
DateKey >= ''
AND DateKey <= ''
GROUP BY
DateKey
GO

但当你再次查看STATISTICS IO的输出,SQL Server还是需要读取很多段,只跳过其中几个:

但为什么SQL Server不能跳过所有的段而只跳过几个?问题存在于聚集列存储的创建。当你回头看刚才的执行计划,你会看到ColumnStore Index Insert (Clustered) 运算符是并行运行的——通过多个工作者线程。而且这些工作者线程再次破坏了聚集列存储索引里你数据的排序!你从聚集行存储索引里进行你的数据读取,然后聚集列索引的并行创建重排了你的数据……伤及无辜~~~

你只能通过使用MAXDOP为1的聚集列存储创建来解决这个问题:

CREATE CLUSTERED COLUMNSTORE INDEX idx_ci ON FactOnlineSales_Temp
WITH (DROP_EXISTING = ON, MAXDOP = 1)
GO

这听起来很糟糕,事实也如此!但这是唯一让你在列存储索引里阻止重排你数据的解决方法。当你接下来从聚集列存储数据读取后,你会看到SQL Server终于能跳过所有的段:

小结

聚集列存储索引很好——真的很好!但默认段消除不能很好进行,因为在你的聚集列存储里没有预定义的排序。因此在你调优你的列存储查询时,你要确保段消除可以正常进行。而且有时候你甚至需要通过使用MAXDOP 1来阻止你的数据排序……

感谢关注!

原文链接:

https://www.sqlpassion.at/archive/2017/01/30/columnstore-segment-elimination

列存储段消除(ColumnStore Segment Elimination)的更多相关文章

  1. 浅谈MSSQL2012中的列存储索引(columnstore indexes)

    列存储索引为MSSQL2012版本中引进的一个新特性.所有版本MSSQL中标准查询处理模式采用一次一行模型,操作符每次处理一行数据.列存储索引中增加了一种新的基于向量的查询执行功能,通过这种功能,操作 ...

  2. SQL Server 2012 列存储索引分析(翻译)

    一.概述 列存储索引是SQL Server 2012中为提高数据查询的性能而引入的一个新特性,顾名思义,数据以列的方式存储在页中,不同于聚集索引.非聚集索引及堆表等以行为单位的方式存储.因为它并不要求 ...

  3. SQL Server 2016:内存列存储索引

    作者 Jonathan Allen,译者 谢丽 SQL Server 2016的一项新特性是可以在“内存优化表(Memory Optimized Table)”上添加“列存储索引(Columnstor ...

  4. SQL Server 列存储索引 第二篇:设计

    列存储索引可以是聚集的,也可以是非聚集的,用户可以在表上创建聚集的列存储索引(Clustered Columnstore Index)或非聚集的列存储索引(Nonclustered Columnsto ...

  5. SQL Server ->> ColumnStore Index(列存储索引)

    Columnstored index是SQL Server 2012后加入的重大特性,数据不再以heap或者B Tree的形式存储(row level)存储在每一个数据库文件的页里面,而是以列为单位存 ...

  6. SQL Server 列存储索引概述

    第一次接触ColumnStore是在2017年,数据库环境是SQL Server 2012,Microsoft开始在SQL Server 2012中推广列存储索引,到现在的SQL Server 201 ...

  7. SQL Server 2014聚集列存储索引

    转发请注明引用和原文博客(http://www.cnblogs.com/wenBlog) 简介 之前已经写过两篇介绍列存储索引的文章,但是只有非聚集列存储索引,今天再来简单介绍一下聚集的列存储索引,也 ...

  8. SQL Server 列存储索引强化

    SQL Server 列存储索引强化 SQL Server 列存储索引强化 1. 概述 2.背景 2.1 索引存储 2.2 缓存和I/O 2.3 Batch处理方式 3 聚集索引 3.1 提高索引创建 ...

  9. 在SQL Server 2014里可更新的列存储索引 (Updateable Column Store Indexes)

    传统的关系数据库服务引擎往往并不是对超大量数据进行分析计算的最佳平台,为此,SQL Server中开发了分析服务引擎去对大笔数据进行分析计算.当然,对于数据的存放平台SQL Server数据库引擎而言 ...

随机推荐

  1. Linux/hp unix/AIX日常巡检脚本(转)

    以下为Linux/hp unix/AIX日常巡检脚本,大家可以参考着进行改写,用于自己的服务器. #!/usr/bin/ksh syserrdate=`date +"%m/%d"` ...

  2. mysql中SQL执行过程详解与用于预处理语句的SQL语法

    mysql中SQL执行过程详解 客户端发送一条查询给服务器: 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果.否则进入下一阶段. 服务器段进行SQL解析.预处理,在优化器生成对应的 ...

  3. uartz Spring与Spring Task总结

    Spring对Quartz作了一个封装,同时,Spring自己也提供了一个任务定时器(spring-task),现把它总结一下.    对于Quartz,我们使用的时候主要是注重两个方面,一个是定时任 ...

  4. js中的 substring和substr方法

    原文: http://www.cnblogs.com/chinafine/archive/2009/02/26/1398771.html 1.substring 方法 定义和用法 substring ...

  5. 数据结构-String、char

    String 常用方法: 获取长度:int length = strl.length() 获取第i个字符:char iChar =  str.charAt(i) String转成字符数组:char[] ...

  6. C++指针与const

    在C++中,const修饰符一般用于修饰常量.常量在定义的时候必须初始化,而且值一旦定义之后就不能修改,这样就能保证常量的值在程序运行过程中不会发生变换. 1.指向const对象的指针 指向const ...

  7. JS内存泄漏排查方法——Chrome Profiles

    一.概述 Google Chrome浏览器提供了非常强大的JS调试工具,Heap Profiling便是其中一个.Heap Profiling可以记录当前的堆内存(heap)快照,并生成对象的描述文件 ...

  8. iOS 之 界面编程解析

    参考:http://www.cocoachina.com/design/20151225/14789.html 0. 内容概述 基础与本质:说明普遍意义上的UI系统的三大模块,让读者从整体上对UI系统 ...

  9. centos5.5开机自动启动服务的方法

    *** chkconfig --list 查看所有的***chkconfig --list smb 查看指定的输出的结果:httpd           0:off   1:off   2:off   ...

  10. 分享Grunt.js配置: watch + liveReload 实时监测文件变化自动刷新浏览器

    http://www.tuicool.com/articles/2eaQJn 用Grunt配置watch和liveReload组件,可以实时检测指定的文件变化并自动刷新浏览器.目前基本已经成为了我的必 ...