翻译之:SQL Server统计信息简介

本文选自《Pro SQL Server Internals》

作者: Dmitri Korotkevitch

出版社: Apress

出版年: 2016-12-29

页数: 804

作者简介:Dmitri Korotkevitchis是微软SQL Server MVP和微软认证大师。作为应用程序和数据库开发人员、数据库管理员和数据库架构师,他具有多年使用SQL Server的经验。他专门从事OLTP系统在高负载下的设计、开发和性能调优。Dmitri经常在各种Microsoft和SQL PASS活动上发言,他为世界各地的客户提供SQL Server培训。

原文链接:http://www.doc88.com/p-4042504089228.html

SQL Server统计信息简介

SQL Server统计信息是系统对象,其中包含有关索引键值中的数据分布的信息,有时还包含常规列值。 可以在支持比较操作的任何数据类型上创建统计信息,例如>,<,=等。

让我们从上一章清单2-15中创建的dbo.Books表中检查IDX_BOOKS_ISBN索引统计信息。您可以使用DBCC SHOW_STATISTICS(‘dbo.Books‘,IDX_BOOKS_ISBN)命令来完成此操作。 结果如图3-1所示。

图3-1 DBCC SHOW_STATISTICS输出

如您所见,DBCC SHOW_STATISTICS命令返回三个结果集。第一个包含有关统计信息的常规元数据信息,例如名称,更新日期,更新统计信息时索引中的行数等。第一个结果集中的“步骤”列指示直方图中的步数/值的数量(稍后将详细介绍)。“查询优化程序”不使用“密度”值,仅出于向后兼容性目的而显示。

第二个结果集称为密度向量,它包含有关统计(索引)中键值组合的密度的信息。它是基于1 /不同值的数量计算得出的,它表示平均每个键值组合有多少行。尽管IDX_Books_ISBN索引只定义了一个键列ISBN,但它还包含一个聚簇索引键作为索引行的一部分。我们的表有1,252,500个唯一的ISBN值,ISBN列的密度为1.0 / 1,252,500 = 7.984032E-07。 (ISBN,BookId)列的所有组合也是唯一的并且具有相同的密度。

最后的结果集称为直方图。直方图中的每个记录(称为直方图步骤)都包括统计信息(索引)最左列中的样本键值以及有关从前一个值到当前RANGE_HI_KEY值的值范围内的数据分布的信息。让我们更深入地检查直方图列。

RANGE_HI_KEY列存储密钥的样本值。 此值是直方图步骤定义的范围的上限键值。 例如,图3-1中直方图中的记录(步骤)#3与RANGE_HI_KEY =‘104-0100002488‘存储有关从ISBN>‘101-0100001796‘到ISBN <=‘104-0100002488‘的间隔的信息。

RANGE_ROWS列估计间隔内的行数。 在我们的例子中,记录(步骤)#3定义的间隔有8,191行。

EQ_ROWS表示有多少行的键值等于RANGE_HI_KEY上限值。 在我们的例子中,只有一行ISBN =‘104-0100002488‘。

DISTINCT_RANGE_ROWS表示密钥的不同值。在这段时间内。在我们的示例中,键的所有值都是唯一的,因此DISTINCT_RANGE_ROWS = RANGE_ROWS。AVG_RANGE_ROWS表示每个不同键的平均行数区间中的值。在我们的例子中,键的所有值都是唯一的,所以AVG_RANGE_ROWS = 1。让我们在索引中插入一组重复的ISBN值,代码如清单3-1所示。

清单3-1 将重复的ISBN值插入索引中。

;with Prefix(Prefix)

as ( select Num from (values(104),(104),(104),(104),(104)) Num(Num) )

,Postfix(Postfix)

as

(

select 100000001

union all

select Postfix + 1 from Postfix where Postfix < 100002500

)

insert into dbo.Books(ISBN, Title)

select

convert(char(3), Prefix) + ‘-0‘ + convert(char(9),Postfix)

,‘Title for ISBN‘ + convert(char(3), Prefix) + ‘-0‘ + convert(char(9),Postfix)

from Prefix cross join Postfix

option (maxrecursion 0);

——更新统计数据

更新统计dbo.Books IDX_Books_ISBN与全扫描;

现在,如果再次运行DBCC SHOW_STATISTICS(‘dbo.Books‘,IDX_BOOKS_ISBN)命令,您将看到如图3-2所示的结果。

图3-2  DBCC SHOW_STATISTICS输出

具有前缀104的ISBN值现在具有重复项,这会影响直方图。 还值得一提的是,第二个结果集中的密度信息也发生了变化。具有重复值的ISBN s的密度高于(ISBN,BookId)列的组合,这仍然是唯一的。

让我们运行SELECT BOOKID,标题FROM dbo.Books WHERE ISBN LIKE“114%”语句,并检查执行计划,如图3-3所示。

图3-3 查询的执行计划

大多数执行计划操作员都有两个重要的属性。 实际行数表示在执行者执行期间处理了多少行。 估计行数表示SQL Server在查询优化阶段为该运算符估计的行数。 在我们的例子中,SQL Server估计有2,625行,其中ISBN以114开头。如果您查看图3-2中所示的直方图,您将看到步骤10存储有关ISBN间隔的数据分布的信息,包括 您正在选择的值。 即使使用线性近似,您也可以估计接近SQL Server确定的行数。

关于统计数据,有两件非常重要的事情需要记住。

1.直方图仅存储有关最左侧统计(索引)列的数据分布的信息。 有关统计中关键值的多列密度的信息,但就是直方图中的所有其他信息仅与最左边的统计列的数据分布有关。

2.无论表的大小和表是否已分区,SQL Server在直方图中最多保留200个步骤。 每个直方图步骤所覆盖的间隔随着表的增长而增加。 这导致在大表格的情况下不太准确的统计数据。

对于复合索引,当索引中的所有列都用作所有查询中的谓词时,将具有较低密度/较高百分比的唯一值的列定义为索引的最左列是有益的。 这将允许SQL Server更好地利用统计信息中的数据分布信息。 但是,您应该考虑谓词的SARGability。 例如,如果所有查询都在where子句中使用FirstName = @ FirstName和LastName = @ LastName谓词,则最好将LastName作为索引中最左侧的列。 尽管如此,对于FirstName = @ FirstName和LastName <> @ LastName之类的谓词不是这种情况,其中LastName不是SARGable。

统计和执行计划

sql服务器默认自动创建和更新统计数据。数据库中有两个选项控制此类行为的级别:

1、自动创建统计控制是否优化程序自动创建列级统计。这个选项不会产生影响,因为索引级统计始终会创建。默认情况下会启用自动创建统计数据库选项。

2、启用自动更新统计数据库选项时,sql服务器每次编译或执行查询时都会检查统计数据是否过时,并在需要时更新统计数据。默认情况下也会启用自动更新统计数据库选项。

提示:您可以通过使用统计计算(STATISTICS_NORECOMPUTE)索引选项来控制索引级别上的统计数据的自动更新行为。默认情况下,此选项将被关闭,意思就是说统计数据默认自动更新。在索引或表级别上改变自动更新行为的另一种方法是使用sp_autostats系统存储过程。

sql服务器根据插入、更新、删除和合并语句执行的影响统计列的更改次数确定统计是否过时。sql服务器计算统计列被更改的次数,而不是更改行的数目。例如,如果您将同一行更改100次,它将被算作100次更改,而不是1次更改。

有三种不同的方案,称为统计更新阈值,有时也称为统计重新编译阈值,其中sql服务器将统计标记为过时。

1、当表为空时,当您将数据添加到表中时,sql服务器将超出统计数据。

2、当表的行少于500行时,每500次统计列的更改,sql服务器就会超出统计数据。

3、2016版sql服务器和之前的版本,具有数据库兼容性级别小于130.如果表中有500行或更多行,则在统计列每500+(占表中行总数的20%)发生变化后,sql服务器就会超出统计数据。

4、2016版sql服务器数据库兼容性级别等于130.大量表的统计数据更新阈值变成动态,而且取决于表的大小。表的行越多,阈值越低。在上百万行甚至数十亿行的大量表格中,统计更新阈值只能是表中行总数百分比的一小部分。此特征也可以在sql服务器2008R2 SP1及更高版本中启用跟踪标志T2371

表3-1总结了不同版本的sql服务器的统计更新阈值行为。

这使我们得出一个非常重要的结论。

使用静态统计更新阈值,触发统计更新所需的统计列的更改数与表大小成正比。表格越大,自动更新的统计数据就越少。例如,在有10亿行的表的情况下,您需要对统计列执行约2亿项更改使统计数据过时。如果可以的话建议使用动态更新阈值。

让我们看看这种行为是如何影响我们的系统和执行计划的。在这一点上,该表dbo.Books有1265000行。我们把250,000行加上前缀999,如表3-5.在此示例中,我使用的是sql服务器2012,未启用T2371。如果启用动态统计更新阈值就可以看到不同的结果。此外,在sql服务器2014中引入的新的基数估计器也可以改变行为。我们会在后面章节中进行讨论。

我们执行SELECT * FROM dbo.Books WHERE ISBN LIKE ‘999%‘ 语句,它可以选择带有此前缀的所有行。

如果检查查询的执行计划,如图3-7所示,您将看到非集群索引查找和键查找操作。

您还会在图3-7中注意到索引查找运算符的估计行数和实际行数之间存在巨大差异。sql服务器估计表中只有31.4行带有前缀999,实际有25万行带有这样的前缀。这就产生了一个非常低效的计划。

接下来,通过DBCC执行命令 SHOW_STATISTICS (‘dbo.Books‘, IDX_BOOKS_ISBN) 看看 IDX_BOOKS_ISBN统计。输出如图3-8所示。如您所见,即使我们在表格中插入了25万行,统计数据也没有更新,而且直方图中没有关于999前缀的数据。第一个结果集中的行数相对应上一个统计期间表中的行数更新。它不包括刚刚插入的250,000行。

通过语句UPDATE STATISTICS dbo.Books IDX_Books_ISBN WITH FULLSCAN更新统计,然后重新执行 SELECT * FROM dbo.Books WHERE ISBN LIKE ‘999%‘ 语句。执行计划如3-9.现在估计的行数是正确的,而sql服务器最终采用了更高效的执行计划,使用的是集群索引扫描,比以前减少了大约17倍的输入/输出读取量。

如你所见,不正确的基数估计会导致执行计划效率低下。过时的统计数据也会是造成基数估计错误的最常见原因之一。您可以通过检查执行计划中的估计行和实际行数来确定其中的一些情况。这两个数值之间的巨大差异往往表明统计数字不正确。更新统计可以解决这个问题,产生更有效率的执行计划。

统计维护

正如我已经提到的,SQL Server默认自动更新统计信息。对于小表,这种行为通常是可以接受的;但是,对于具有数百万或数十亿行的大型表,您不应该依赖自动统计信息更新,除非您使用的SQL Server 2016的数据库兼容级别为130或启用了跟踪标志T2371。按20%统计信息更新阈值触发统计信息更新所需的更改次数将非常高,因此,不会经常触发更新。

在这种情况下,建议您手动更新统计信息。在选择最佳统计维护策略时,您必须分析表的大小,数据修改模式和系统可用性。例如,如果系统在工作时间之外没有负载,您可以决定每晚更新关键表的统计信息。不要忘记统计信息和/或索引维护会为SQL Server增加额外的负载。 您必须分析它如何影响同一服务器和/或磁盘阵列上的其他数据库。

设计统计维护策略时需要考虑的另一个重要因素是如何修改数据。对于具有不断增加或减少的键值的索引,您需要更频繁地更新统计信息,例如当索引中最左侧的列定义为标识或使用序列对象填充时。如您所见,如果特定键值超出直方图,SQL Server会大大低估行数。 在SQL Server 2014到2016中,此行为可能会有所不同,我们将在本章后面部分中看到。

您可以使用UPDATE STATISTICS命令更新统计信息。 当SQL Server更新统计信息时,它会读取数据样本而不是扫描整个索引。 您可以使用FULLSCAN选项更改该行为,该选项强制SQL Server读取和分析索引中的所有数据。 正如您可能猜到的那样,该选项提供了最准确的结果,尽管它可能会引入大量的I / O活动大表的情况。

提示重建索引时,SQL Server会更新统计信息。 我们将在第6章“索引碎片化”中更详细地讨论索引维护。

您可以使用sp_updatestats系统存储过程更新数据库中的所有统计信息。 建议您使用此存储过程并在将其升级到新版本的SQL Server后更新数据库中的所有统计信息。 您应该与DBCC UPDATEUSAGE存储过程一起运行它,它会更正目录视图中不正确的页面和行计数信息。

有一个sys.dm_db_stats_properties DMV,它显示自上次统计信息更新以来对统计信息列所做的修改次数。 利用该DMV的代码如清单3-9所示。

清单3-9 使用sys.dm_db_stats_properties

select

s.stats_id as [Stat ID], sc.name + ‘.‘ + t.name as [Table], s.name as [Statistics] ,p.last_updated, p.rows, p.rows_sampled, p.modification_counter as [Mod Count]

from sys.stats s join sys.tables t on s.object_id = t.object_id join sys.schemas sc on

t.schema_id = sc.schema_id outer apply sys.dm_db_stats_properties(t.object_id,s.stats_id) p

where

sc.name = ‘dbo‘ and t.name = ‘Books‘;

查询结果如图3-11所示,表明自上次统计信息更新以来,对统计信息列进行了250,000次修改。 您可以构建统计信息维护例程,定期检查sys.dm_db_stats_properties DMV并使用较大的modification_counter值重建统计信息。

图3-11  Sys.dm_db_stats_properties outp

另一个与统计相关的数据库选项是异步自动更新统计信息。 默认情况下,当SQL Server检测到统计信息已过时时,它会暂停查询执行,同步更新统计信息,并在统计信息更新完成后生成新的执行计划。 通过异步统计信息更新,SQL Server使用旧的执行计划执行查询,该计划基于过时的统计信息,同时异步更新后台统计信息。 建议您继续使用同步统计信息更新除非系统具有非常短的查询超时,在这种情况下,同步统计信息更新可以使查询超时。

最后,SQL Server不会在您创建新索引时自动删除列级统计信息。您应该手动删除冗余的列级统计信息对象。

新基数估算器(SQL Server 2014-2016)

如您所知,查询优化的质量取决于准确的基数。SQL Server必须正确估计查询执行的每个步骤中的行数,以便生成有效的执行计划。最初使用SQL Server 2005-2012中使用的基数估算模型为SQL Server 7.0开发并于1998年发布。显然,在较新版本的SQL Server中有一些小的改进和更改; 然而,从概念上讲,模型保持不变。

模型中使用了四个主要假设,包括:

均匀性:该模型假设在没有统计信息的情况下统一数据分布。例如,在直方图内部步骤中,假设所有键值均匀且均匀地分布。

独立性:此模型假设实体中的属性彼此独立。例如,当查询针对同一个表的不同列有多个谓词时,它会假定列不以任何方式相关。

简单包含:此模型假定用户查询表中存在的数据。例如,当您连接两个表时,如果没有统计信息,模型会假定一个表中的所有不同值都存在于另一个表中。此模型中连接运算符的选择性基于连接谓词的选择性。

包含:此模型假定当将属性与常量进行比较时,始终存在匹配。

原文地址:https://www.cnblogs.com/CTHK/p/10147429.html

时间: 2024-12-08 18:20:49

翻译之:SQL Server统计信息简介的相关文章

全废话SQL Server统计信息(1)——统计信息简介

当心空无一物,它便无边无涯.树在.山在.大地在.岁月在.我在.你还要怎样更好的世界?--张晓风<我在> 为什么要写这个内容? 随着工作经历的积累,越来越感觉到,大量的关系型数据库的性能问题,其根源在于统计信息.这里说的是根源,其实很多时候大家觉得的那些什么索引失效等都只是表象.当然,不能一概而论,还有很多问题如配置问题.设计问题等等,甚至电源也会影响性能. 之所以得出这个结论,因为在常规的开发和部署过程中,一般企业级系统已经大量使用较为高级的磁盘阵列甚至企业级SSD,IO方面的问题已经很少,而

SQL Server统计信息:问题和解决方式

在网上看到一篇介绍使用统计信息出现的问题已经解决方式,感觉写的很全面. 在自己看的过程中顺便做了翻译. 因为本人英文水平有限,可能中间有一些错误. 假设有哪里有问题欢迎大家批评指正.建议英文好的直接看原文:SQL Server Statistics: Problems and Solutions 正文: SQL Server统计信息协助查询优化器计算执行查询的最优方式. Holger描写叙述了常见的统计信息出错的事情,而且怎样改善 通常你不须要太操心运行SQL查询的方式.他们被传送到查询优化器,

SQL Server统计信息:问题和解决方案

在网上看到一篇介绍使用统计信息出现的问题已经解决方案,感觉写的非常全面.在自己看的过程中顺便做了翻译.由于本人英文水平有限,可能中间有一些错误.如果有哪里有问题欢迎大家批评指正.建议英文好的直接看原文:SQL Server Statistics: Problems and Solutions 正文: SQL Server统计信息协助查询优化器计算运行查询的最优方式. Holger描述了常见的统计信息出错的事情,并且如何改善 通常你不需要太担心执行SQL查询的方式.他们被传送到查询优化器,首先检查

SQL Server 统计信息维护策略的选择

SQL Server 统计信息维护策略的选择 问题描述: 在对OLTP系统的一个上千万的表做归档后,循环分批删除源表数据时,业务应用收到超时告警,如下: V1.1.1.1: ****Process - QueryTransactionFor****: 23075129 Timeout expired.   The timeout period elapsed prior to completion of the operation or the server is not responding.

SQL Server 统计信息(Statistics)-概念,原理,应用,维护

前言:统计信息作为sql server优化器生成执行计划的重要参考,需要数据库开发人员,数据库管理员对其有一定的理解,从而合理高效的应用,管理. 第一部分 概念 统计信息(statistics):描述某个(些)栏位,索引的数据分布情况.优化器用其评估生成高效执行计划. 密度(density):一个比率值,显示在一个(组)列中有多少唯一值.(实际应用中值越小越好) Density = 1 / Number of distinct values for column(s) 直方图(histogram

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

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

SQL Server统计信息偏差影响表联结方式案例浅析

原文:SQL Server统计信息偏差影响表联结方式案例浅析   我们知道数据库中的统计信息的准确性是非常重要的.它会影响执行计划.一直想写一篇关于统计信息影响执行计划的相关博客,但是都卡在如何构造一个合适的例子上,所以一直拖着没有写.巧合,最近在生产环境中遇到这么一个案例,下面对案例中的相关信息做了脱敏处理,有些中间步骤也省略了,只关注核心部分SQL.如下所示,同事反馈一个SQL语句执行很慢.   UPDATE  b SET     b.[Status] = '已扫描,未签收' ,      

SQL Server 统计信息

SELECT * FROM SYS.stats _WA_Sys_00000009_00000062:统计对象的名称.不同的机器名称不同,自动创建的统计信息都以_WA_Sys开头,00000009表示的是第几列,后面的数是一个十六进制的数,等于表的object_id,WA是华盛顿,是sql server开发组所在地

SQL SERVER 统计信息概述(Statistics)

前言 查询优化器使用统计信息来创建可提高查询性能的查询计划,对于大多数查询,查询优化器已经为高质量查询计划生成必要的统计信息,但是在少数情况下,您需要创建附加的统计信息或者修改查询设计以得到最佳结果.因此理解和合理使用统计信息是数据库优化的方式之一.   统计信息的分类 根据创建源的不同,统计信息分为两种表统计信息和索引统计信息,除非你自定义它们,否则它们之间没有本质的区别. 索引统计信息建立在索引上面,因此对于创建已经存在的数据上,在创建索引的时候会扫描全部数据,这些数据也会创建在索引的统计信