关于SQL-Server的统计信息介绍

经常会有遇到一些sql-server用户遇到关于统计信息的问题:

  1. 为什么query在有时候会偶发性的出现慢?
  2. 为什么在执行query时,需要更新统计信息?

SQL Server在运行指令的时候,也要知道所涉及的表格每个有多大,预期每张表格能够返回多少数据,每一步的结果集会多大。知道了这些信息,才能够选择比较好的执行计划。可是SQL Server是一个计算机程序,它是怎么知道这些信息的呢?这要靠statistics(统计信息)来帮忙。SQL Server会在每个索引上自动建立统计信息,也会根据运行指令的需要,动态地创建一些统计信息。统计信息的准确度,会直接影响SQL Server完成指令的速度。

下面截图显示在表top5m(有500万行)中,在20130107这个range里面Range-rows为13162,EQ_ROWS为15992,distinct_range_rows等于2,Avg_Range_rows为6581.
关于SQL-Server的统计信息介绍

下面的结果给了非常明确的解释,6691+6471=13162. 13162/2=6581. 所以 Range_Hi_Key为20130107,指的是这个range的最大值,Range_rows是指的是中间的结果总数,EQ_Rows只是等于这个最大值的数据量。

关于SQL-Server的统计信息介绍

列名 说明
Name 统计信息的名称。这里就是索引的名字,SalesOrderHeader_test_CL
Updated 上一次更新统计信息的日期和时间。这里是2009/8/29 3:00PM。这个时间非常重要,根据它能够判断统计信息是什么时候更新的,是不是在数据量发生变化以后,是不是存在统计信息不能反映当前数据分布特点的问题
Rows 表中的行数。完全正确地反映了当前表里数据量
Rows Sampled 统计信息的抽样行数
Steps 在统计信息的第三部分,会把数据分成几组。这里是3组。(分组的依据是什么?答:会根据数据的一个分部情况来分,根据数据‘长得像不像’来分。)
Density 第一个列前缀的选择性(不包括 EQ_ROWS)。
Average key length 所有列的平均长度。因为SalesOrderHeader_test_CL索引只有一列,数据类型是int,所以长度就是4。
String Index 如果为“是”,则统计信息中包含字符串摘要索引,以支持为 LIKE 条件估算结果集大小。仅适用于 char、varchar、nchar 和 nvarchar、varchar(max)、nvarchar(max)、text 以及 ntext 数据类型的前导列。这里是int,所以这个值是”NO”。

###统计信息的会在什么时候进行自动更新:
SQL Server不仅要建立合适的统计信息,还要及时更新它们,使它们能够反映表格里数据的变化。数据的插入、删除、修改都可能会引起统计信息的更新。但是,更新统计信息本身也是一件消耗资源的事情,尤其是对比较大的表格。如果有一点点小的修改SQL Server都要去更新统计信息,可能SQL Server就得光忙活这个,来不及做其他事了。SQL还是要在统计信息的准确度和资源合理消耗之间作一个平衡。在SQL 2005&2008,触发统计信息自动更新的条件是:

· 如果统计信息是定义在普通表格上的,那么当发生下面变化之一后,统计信息就被认为是过时的了。下次使用到时,会自动触发一个更新动作。
        1. 表格从没有数据变成有大于等于1条数据。
        2. 对于数据量小于500行的表格,当统计信息的第一个字段数据累计变化量大于500以后。

对于数据量大于500行的表格,当统计信息的第一个字段数据累计变化量大于500 + (20% * 表格数据总量)以后。所以对于比较大的表,只有1/5以上的数据发生变化后,SQL Server才会去重算统计信息。

回到最开始的两个问题:

  1. 其实是由于有些统计信息只会在query在执行的被进行自动更新。真正的执行。
  2. 由于不更新统计信息的话,那么优化器对query执行选择的执行计划就会不准确。
上一篇:一篇文章深入浅出带你了解mybatis


下一篇:阿里云Redis配置公网连接的注意点