【第12周翻译】《Pro SQL Server Internals, 2nd edition》的CHAPTER 3 Statistics中的Introduction to SQL Server Statistics一节(即P55~P58)、Statistics and Execution Plans(P62~P65)、Statistics Maintenance(P68~P69)共三小节。

SQL Server统计信息简介

SQLServer统计信息是包含索引键的值中的数据分布的信息的系统对象,有时也包含在常规列值中。可以对支持比较操作的任何数据类型(如>、<、=)创建统计信息。

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

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

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

最后一个结果集称为柱状图。柱状图中的每个记录称为柱状图步骤,包括统计(索引)最左边一列中的样本键值,以及从上一个值到当前RANGE_HI_KEY值范围内的数据分布信息。让我们更深入地研究柱状图列。

RANGE_HI_KEY 列存储键的样本值。该值是由柱状图步骤定义的范围的上限键值。例如,在图3-1的柱状图中,用 RANGE_HI_KEY = '104-0100002488'  记录(步骤)#3,来存储有关从ISBN > '101-0100001796'  到 ISBN <= '104-0100002488'  的间隔的信息。

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

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); -- Updating the statistics update statistics dbo.Books IDX_Books_ISBN with fullscan; 

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

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

让我们运行  SELECT BookId, Title FROM dbo.Books WHERE ISBN LIKE ‘114%’ 语句,并检查执行计划,如图3-3所示。

大多数执行计划操作员都具有两个重要属性。实际行数(  Actual Number of Rows )指示在执行运算符期间处理了多少行。估计行数( Estimated Number of Rows )指示在查询优化阶段为该运算符估计的SQL Server行数。在我们的例子中,SQL Server估计有2625行的ISBNs从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 Server自动创建和更新统计信息。数据库级别上有两个选项控制此类行为:

1.自动创建统计信息(Auto Create Statistics )控制优化器是否自动创建列级统计信息。此选项不影响始终创建的索引级统计信息。默认情况下,自动创建统计数据数据库选项处于启用状态。

2.启用自动更新统计信息数据库(Auto Update Statistics  database)选项后,SQL Server会在每次编译或执行查询时检查统计信息是否过期,并在需要时进行更新。默认情况下也启用自动更新统计数据库选项。

提示:您可以使用  STATISTICS_ NORECOMPUTE 索引选项来控制索引级统计信息的自动更新行为。默认情况下,此选项设置为关闭(OFF),这意味着统计信息将自动更新。在索引或表级更改自动更新行为的另一种方法是使用 sp_autostats 系统存储过程。

SQL Server根据影响统计信息列的 INSERT、UPDATE、DELETE和 MERGE (插入、更新、删除和合并)语句所执行的更改数确定统计信息是否过期。SQL Server计算更改统计信息列的次数,而不是更改的行数。例如,如果您对同一行进行100次更改,它将被计算为100次更改,而不是1次更改。

有三种不同的设想,称为统计信息更新阈值,有时也称为统计信息重新编译阈值,其中SQL Server将统计信息标记为过期。

1.当表为空时,在向表中添加数据时,SQL Server将统计信息标记为过期。

2.当表的行数小于500行时,SQL Server会在统计信息列每更改500次后,将统计信息标记为过期。

3.在SQL Server 2016之前和在数据库兼容级别<130的SQL Server 2016中:当一个表有500行或更多行时,SQL Server会在统计信息列的每500+次(表中行总数的20%)更改后将统计信息标记为过期。

在数据库兼容级别=130的SQL Server 2016中:大型表上的统计信息更新阈值将变为动态的,并取决于表的大小。表中的行越多,阈值越低。对于具有数百万甚至数十亿行的大型表,统计信息更新阈值可能只是表中行总数的百分比的一小部分。还可以使用SQL Server 2008R2 SP1及更高版本中的跟踪标志 T2371 启用此行为。

表3-1总结了不同版本的SQL Server中的统计信息更新阈值行为。

表3-1 统计更新阈值和SQL Server版本
  在SQL Server 2016之前 数据库兼容级别<130的SQL Server 2016 数据库兼容级别=130的SQL Server 2016

默认行为

静态(~20%)阈值

静态(~20%)阈值

动态阈值
T2371 SQL Server 2008R2 SP1及更高版本中的动态阈值 动态阈值

动态阈值

(跟踪标志被忽略)

这使我们得出了一个非常重要的结论。对于静态统计信息更新阈值,触发统计信息更新所需的统计信息列更改数与表大小成比例。表越大,自动更新统计信息的频率就越低。例如,对于具有10亿行的表,您需要对统计信息列执行大约2亿次更改,才能使统计信息过期。建议尽可能使用动态更新阈值。

让我们看看这种行为是如何影响我们的系统和执行计划的。假设有这么一个情况,表  dbo. Books 有126500行。让我们用前缀999向表中添加250000行,如清单3-5所示。在这个例子中,我使用的是未启用T2371的SQL Server 2012。如果在启用动态统计信息更新阈值的情况下运行它,则可以看到不同的结果。此外,SQL Server 2014中引入的新基数估计量也可以改变这种行为。我们将在本章后面讨论。

清单3-5: dbo.Books 中添加行

;with Postfix(Postfix) as ( select 100000001 union all select Postfix + 1 from Postfix where Postfix < 100250000 ) insert into dbo.Books(ISBN, Title) select '999-0' + convert(char(9),Postfix) ,'Title for ISBN 999-0' + convert(char(9),Postfix) from Postfix option (maxrecursion 0); 

现在,让我们运行  SELECT * FROM dbo.Books WHERE ISBN LIKE '999%' 查询,它选择具有此类前缀的所有行。

如果检查查询的执行计划(如图3-7所示),您将看到非聚集索引查找和键查找操作,尽管在需要从表中选择几乎20%的行的情况下,它们的效率仍然很低。

您还将在图3-7中注意到,索引查找运算符的估计行数和实际行数之间存在巨大的差异。即使事实上有25万行的前缀为999,但是SQL Server估计在表中前缀为999的行只有31.4行。因此,产生了一个效率极低的计划。

让我们通过运行 DBCC SHOW_STATISTICS ('dbo.Books', IDX_ BOOKS_ISBN) 命令来查看  IDX_BOOKS_ISBN 的统计信息。输出如图3-8所示。正如您所看到的,即使我们在表中插入了250000行,统计信息也没有更新,并且前缀999的柱状图中也没有数据。第一个结果集中的行数与上次统计更新期间表中的行数相对应。它不包括刚刚插入的250000行。

现在让我们使用  UPDATE STATISTICS dbo.Books IDX_Books_ISBN WITH FULLSCAN  命令更新统计信息,然后再次运行  SELECT * FROM dbo.Books WHERE ISBN LIKE '999%' 查询。查询的执行计划如图3-9所示。现在SQL Server估计的行数是正确的,并且SQL Server最终得到了一个更高效的执行计划,该计划使用的聚集索引扫描的I/O读取次数比以前少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,它显示自上次统计信息更新以来对统计信息列所做的修改数。清单3-9显示了利用DMV的代码。

清单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所示,表明自上次统计信息更新以来,对统计信息列进行了250000次修改。您可以构建一个统计信息维护常规,来定期检查  sys.dm_db_stats_properties  DMV ,并使用较大的 modification_ counter  值重建统计信息。

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

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

原著信息:

此篇文章翻译自《Pro SQL Server Internals, 2nd edition》的CHAPTER 3 Statistics中的Introduction to SQL Server Statistics一节(即P55~P58)、Statistics and Execution Plans(P62~P65)、Statistics Maintenance(P68~P69)共三小节。

原著:《Pro SQL Server Internals, 2nd edition》    原文作者:Dmitri Korotkevitch

翻译《Pro SQL Server Internals,2nd edition》的CHAPTER 3 Statistics的Introduction to SQL Server Statistics等相关推荐

  1. Pro SQL Server Internals, 2nd edition》CHAPTER 1 Data Storage Internals节选翻译

    翻译原文:<Pro SQL Server Internals, 2nd edition>CHAPTER 1 Data Storage Internals 作者:Dmitri Korotke ...

  2. 第八周翻译:《Pro SQL Server Internals, 2nd edition》CHAPTER 1 Data Storage Internals Data Pages and DataRow

    译者:薛朝鹏,张鹏辉 数据库中的空间分为逻辑8KB页面. 这些页面从零开始连续编号,可以通过指定文件ID和页码来引用它们. 页面编号始终是连续的,这样当SQL Server增长数据库文件时,新页面将从 ...

  3. 《Pro SQL Server Internals, 2nd edition》CHAPTER 2 Tables and Indexes-Clustered Indexes

    一.聚集索引 作者:薛朝鹏,张鹏辉 聚集索引指示表中数据的物理顺序,该表根据聚簇索引键进行排序. 该表只能定义一个聚集索引. 假设您要在堆表上使用数据创建聚集索引. 作为第一步,如图2-5所示,SQL ...

  4. 《Pro SQL Server Internals, 2nd edition》CHAPTER 3 Statistics

    作者:薛朝鹏 张鹏辉 统计信息简介 SQL Server统计信息是系统对象,其中包含有关索引键值中的数据分布的信息,有时还包含常规列值. 可以在支持比较操作的任何数据类型上创建统计信息,例如>, ...

  5. 《Pro SQL Server Internals, 2nd edition》节选翻译(一)

    章节1:数据存储内部构件 数据页和数据行 数据库中的空间被划分为有逻辑结构的页面,每页8KB.这些页面从0开始连续编号,可以通过指定文件ID和页码来引用它们.页面编号总是连续的,这样当SQL Serv ...

  6. 《Pro SQL Server Internals, 2nd edition》节选翻译(4)

    本文是<Pro SQL Server Internals, 2nd edition>节选翻译,原书下载地址:https://rejoice.ctfile.com/fs/1475340-23 ...

  7. 第十五周翻译-《Pro SQL Server Internals, 2nd edition》

    <Pro SQL Server Internals, 2nd edition> 作者:Dmitri Korotkevitch 翻译:赖慧芳 译文: 55-58页 第三章 统计 SQL Se ...

  8. 《Pro SQL Server Internals, 2nd edition》 作者:Dmitri KorotkevitchP55-58 P62-65 P68-69

    55-58页 第三章 统计 SQL Server查询优化器在为查询选择执行计划时使用基于成本的模型.它估计不同执行计划的成本,并选择成本最低的一个.但是,请记住,SQL Server并不搜索可用于查询 ...

  9. 推荐: SQL Server Management Express Edition插件

    如果使用SQL Server2005的Express版本时,不可避免需要使用SQL Server Management  Express Edition.而2005版本之前的管理器中书写SQL.查找字 ...

最新文章

  1. RecursionError: maximum recursion depth exceeded
  2. Visual Studio2005入门.Net系列视频教程
  3. [NOIP2012提高组]国王游戏
  4. (笔记)java环境变量设置
  5. 云计算技术前景怎么样?
  6. URL重写 对于禁用cookie的 方法
  7. 接口XMPPConnection
  8. 复位BIOS解决电脑启动死机
  9. 浅谈新一代PGIS技术在智慧消防中的创新应用
  10. 关于一个正弦波程序表格生成器
  11. SQLServer过期解决步骤
  12. 数据结构和算法之二叉树左视图
  13. mysql问题系列(一)-----No space left on device
  14. C语言 谭浩强 题目 -第八章
  15. 每日一道 LeetCode (16):求 x 的平方根
  16. 浅析 vue-router 源码和动态路由权限分配
  17. 自动化测试概述/自动化工具
  18. 基于python的Topsis(优劣解距离)算法的实现(附代码及举例说明)
  19. 什么是模块化?模块化的好处是什么?
  20. 1张上海各阶层本科生真实工资表流出,戳穿了对年轻人最残忍的骗局

热门文章

  1. 用SkinMagic工具包创建换皮肤程序
  2. 当知识图谱遇上推荐系统之MKR模型(论文笔记三)
  3. 哈希表构造与处理冲突方法
  4. Spring学习笔记(三十二)——SpringBoot中cache缓存的介绍和使用
  5. 如何通过互联网赚钱?
  6. Visual Studio2022编译报错解决方法
  7. 什么是sku转载网上,备忘一个业务知识
  8. 发烧后的咽喉肿痛自我治疗
  9. 2-灵魂存在与否的论证(1)(耶鲁大学公开课-哲学-死亡)
  10. 北航和北理工计算机专业哪个好,北理和北航哪个好?