理解统计信息(0/6):密度

在日常生活中,我们用统计信息来采取决定。SQL Server优化器也用同样的方式,使用统计信息来选择正确的执行计划。如果统计信息错误或过期,SQL Server可能就会选择错误的执行计划。在这个文章里,我们换个方式理解下统计信息。

查询优化器使用统计信息来判断每一步返回的行。执行计划里的估计行数信息是基于列的可用统计信息计算而来的。统计信息给我们列里数据分布情况。没有统计信息,查询优化器不呢个判断不同计划的效率。通过使用统计信息,查询优化器在访问数据时可以做出正确的选择。

在我们定义索引时,统计信息会自动创建。除此之外,当列在查询里被引用,作为WHERE条件的一部分,在group by子句里或join条件里,统计信息都会创建。为了自动创建统计信息,在数据库层里的AUTO_CREATE_STATISTICS 设置应该被启用。默认情况下这个设置是被启用的。除此之外,统计信息可以使用CREATE STATISTICS命令创建。

在SQL Server里存储的统计数字是关于密度和直方图(数据分布)的信息。在我们讨论更多细节前,先理解这2个概念。

密度:在给出列或一组列惟一值的比例。统计密度的公式:1/列(或一组列)不同值个数。

密度用来衡量列的唯一性或列的选择性。密度的值在0和1之间。如果这列的密度值为1,表示这列的所有记录值一样,选择性低。更高的密度带来更低的选择性。如果这列的密度值为0.003,表示这列有1/0.003=333个不同值。

我们来看个例子,用下列语句创建表并在上面建立2个索引。

1 USE StatisticsDB
2 GO
3
4 SELECT * INTO SalesOrderDetail FROM AdventureWorks2008R2.Sales.SalesOrderDetail
5 CREATE UNIQUE CLUSTERED INDEX ix_SalesOrderDetailID ON SalesOrderDetail(SalesOrderDetailID)
6 CREATE NONCLUSTERED INDEX ix_productid ON SalesOrderDetail(productid)

我们来看看这2个索引的统计信息。

1 DBCC SHOW_STATISTICS(‘dbo.SalesOrderDetail‘, ‘ix_SalesOrderDetailID‘)

输出结果有3个表,分别是:统计信息头,密度和直方图。

在第1部分(统计信息头)

  • Name :索引名称
  • Updated :统计信息更新时间
  • Rows :索引里行数目。不是表里的行数。
  • Rows Sampled :用于生成统计信息的采样行数。创建索引的时候,会进行完全扫描。
  • Steps :直方图里的步长。(第3部分的内容)
  • Density :在SQL Server里不再使用,向老版本兼容。
  • Average key length :索引键平均长度。
  • String Index :用于like时估计统计行数。
  • Filter Expression :过滤索引表达式
  • Unfiltered Rows :未过滤的行数,如果不存在过滤索引,则等同于Row列。

可以使用DBCC SHOW_STATISTICS加WITH STAT_HEADER来只获取统计头信息。

在第2部分的密度表,我们只看到一条记录,因为在我们索引里只有1列。

所有密度列给我们SalesOrderDetailsId 列的密度值(1/列(或一组列)不同值个数)。所有密度列给我们值 8.242868E-06 =0.000008242868。这表示SalesOrderDetailsId 列有 1/0.000008242868=121317个唯一值,我们可以用下列语句验证下。

1 SELECT COUNT(DISTINCT SalesOrderDetailID ) FROM SalesOrderDetail

可以使用DBCC SHOW_STATISTICS加WITH DENSITY_VECTOR来只获取密度信息。

我们来看看非聚集索引ix_productid的密度。

1 DBCC SHOW_STATISTICS(‘dbo.SalesOrderDetail‘, ‘ix_productid‘) WITH DENSITY_VECTOR

在密度表里可以看到2行记录,即使我们的非聚集索引是在单列上。这是因为聚集键是非聚集索引的一部分(参见索引深入浅出(4/10):非聚集索引的B树结构在聚集表)。

第一行告诉我们,ProductID 列的密度值为0.003759399,换句话说,在ProductID列有1/0.003759399=226个唯一值。我们可以验证下。

1 SELECT COUNT(DISTINCT ProductID) FROM dbo.SalesOrderDetail

第二行告诉我们,ProductID和SalesOrderDetailID组合列的密度值是0.000008242868,换句话说,ProductID和SalesOrderDetailID组合列有121317个唯一值,这个和表的总记录数是一致的。

密度值会用在哪里呢,我们看下下面查询的执行计划,点击工具栏的显示包含实际的执行计划。

1 SELECT ProductID,COUNT(*) FROM dbo.SalesOrderDetail GROUP BY ProductID

在执行计划里,在流聚合运算符的输出里,我们看到估计行数是266。在ProductID列唯一值(个数)可以从密度表里拿到。但我们怎么证明查询优化器是用这个值来计算估计行数。我们创建另外一个没有任何索引的SalesOrderDetail表。

1 SELECT * INTO SalesOrderDetail_NoStats FROM SalesOrderDetail

通过下面语句我们可以看出,这表没有任何的统计信息。

1 EXEC SP_HELPSTATS ‘SalesOrderDetail_NoStats‘, ‘ALL‘

我们再看下这个表的刚才查询,点击工具栏的显示包含实际的执行计划:

1 SELECT ProductID,COUNT(*) FROM dbo.SalesOrderDetail_NoStats GROUP BY ProductID

在没有任何统计索引和统计信息的情况下,优化器再一次在流聚合运算符的输出里估计行数是266。我们再次检查下这个表的统计信息。

1 EXEC SP_HELPSTATS ‘SalesOrderDetail_NoStats‘, ‘ALL‘

是的,在估计执行计划是,SQL Server在productID 列创建了统计信息来帮助优化器选择正确的执行计划。我们来看看这个统计信息的详情。

1 DBCC SHOW_STATISTICS(‘dbo.SalesOrderDetail_NoStats‘, ‘_WA_Sys_00000005_7E6CC920‘) 

在统计信息头,我们注意到Rows Sampled 值比Rows值小。这是因为在自动创建统计信息时,SQL Server没有扫描整个表,只扫描了表的样本。为什么会这样在接下来的文章里会谈到。简而言之,在非聚集索引字段里,统计信息帮助优化器在每一步操作时判断估计行数,什么样的连接是合适的,还有在计划中的执行顺序。

时间: 2024-11-17 06:18:21

理解统计信息(0/6):密度的相关文章

理解统计信息(2/6):直方图

在理解统计信息(1/6):密度里,我们讨论了在统计里存储的密度信息.这篇文章会讨论下直方图.我们再次创建SalesOrderDetail表的副本,并在上面建立2个索引. 1 USE StatisticsDB 2 GO 3 SELECT * INTO SalesOrderDetail FROM AdventureWorks2008r2.Sales.SalesOrderDetail 4 CREATE UNIQUE CLUSTERED INDEX ix_SalesOrderDetailID ON Sa

理解统计信息(3/6):谁创建和管理统计信息?在性能调优中,统计信息的作用。

在理解统计信息(2/6):直方图 中,我们讨论了直方图,密度,还有SQL Server如何用统计信息做基数预估(cardinality estimation).这篇文章会讨论统计信息如何被创建,还有统计信息在性能调优中的重要性. 有2类统计信息,索引统计信息和列统计信息.索引统计信息是索引创建的一部分(建立索引会自动创建索引统计信息).在where条件列被引用或查询的group by子句里包含列,列统计信息都会由SQL Server自动创建. 有数据库属性设置里,可以设置数据库是否自动创建统计信

理解统计信息(6/6):统计信息汇总贴

在帮助优化器选择正确的执行计划,统计信息是一个重要因素.因此,我们在处理性能问题时,要足够重视统计信息.可能是对统计信息知识及其相关机制的缺乏,忽略统计信息往往是造成性能问题的根源. 查询优化器在每一步使用统计信息判断返回的行数.在执行计划里的预估行数信息是基于列上的可用统计信息计算而来的.统计信息会给我们列上数据分布信息.没有统计信息,查询优化器不能判断不同计划的效率.通过使用统计信息里的内容,查询优化器在访问数据的时候就可以做出正确选择. 在SQL Server里存储的统计信息包括密度和直方

理解统计信息(4/6):自动更新统计信息的阀值——人为更新统计信息的重要性

在理解统计信息(3/6):谁创建和管理统计信息?在性能调优中,统计信息的作用里我们讨论了统计信息的自动创建和自动更新.我们真的需要人为维护统计信息来保持性能最优?答案是肯定的,这取决与你的工作量.SQL Server只在达到阀限值时进行统计信息的自动更新.当大量的Insert/Update/Delete操作发生时,内建的自动更新统计信息不能持续保证性能的最优. 经过一系列的Insert/Update/Delete后,统计信息可能不会是最新.如果SQL Server查询优化器在表里需要指定列的统计

理解统计信息(5/6):如何检测过期的统计信息

在 理解统计信息(4/6):自动更新统计信息的阀值——人为更新统计信息的重要性 里,我们讨论了自动更新统计信息的阀值,这个阀值在某些情况下,基于自动更新的统计信息还是可以获得最优的执行计划的.在大多数情况下,人为更新统计信息可以获得更好的性能.这个文章,我们可以来看下如何检测过期的统计信息. 在SQL Server 2005以后的版本里,SQL Server使用ColModCtr 对统计的主要列对象进行跟踪.但在 SQL server 2005或SQL server 2008里没有对应的DMV进

SQL Server 统计信息理解

前言 Sqlserver 查询是基于开销查询的,在首次生成执行计划时,是基于多阶段的分析优化才确定出较好的执行计划.而这些开销的基数估计,是根据统计信息来确定的.统计信息其实就是对表的各个字段的总体数据进行分段分布,数据库默认都会自动维护. 表和视图都有统计信息,统计信息对象是根据索引或表列的列表创建的.当某列第一次最为条件查询时,将创建单列的统计信息.当创建索引时,将创建同名的统计信息.索引中,统计信息只统计首列,因此索引除了按首列排序存储数据外,其统计信息也是按首列计算统计的,所以索引设置时

全废话SQL Server统计信息(2)——统计信息基础

接上文:http://blog.csdn.net/dba_huangzj/article/details/52835958 我想在大地上画满窗子,让全部习惯黑暗的眼睛都习惯光明--顾城<我是一个任性的孩子> 这一节主要介绍一些理论层面的东西,主要针对SQL Server,为后面的做铺垫.假设从实操层面考虑能够跳过,可是我强烈建议还是要找时间看一下这节.本节的内容例如以下: SQL Server统计信息 列级统计信息 统计信息与运行计划 统计信息与内存分配 开销预估模型 SQL Server统计

使用过滤统计信息解决参数预估错误

参数预估是SQL Server里一颗隐藏的宝石.一般而言,参数预估指的是,在查询编译期间,查询优化器尝试找出在执行计划里从各个运算符平均返回的行数.这个估计用来驱动计划本身生成并选择正确的计划运算符——例如像Nested Loop, Merge Join,还是Hash Join的物理连接.当这些估计错误时,查询优化器就会选择错误的计划运算符,相信我——你的查询就会非常非常非常慢! 查询优化器使用称为统计信息对象作为参数预估.每次当你创建一个索引,SQL Server在下面也会创建一个统计对象.这

使用自增长键列值的统计信息

原文:使用自增长键列值的统计信息 今天的文章里我想谈下SQL Server里非常普遍的问题:如何处理用自增长键列的统计信息.我们都知道,在SQL Server里每个统计信息对象都有关联的直方图.直方图用多个步长描述指定列数据分布情况.在一个直方图里,SQL Server最大支持200的步长,但当你查询的数据范围在直方图最后步长后,这是个问题.我们来看下面的代码,重现这个情形: 1 -- Create a simple orders table 2 CREATE TABLE Orders 3 (