第十二周翻译

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不会自动删除列级统计信息。您应该手动删除冗余的列级统计数据对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Improve your ability to develop, manage, and troubleshoot SQL Server solutions by learning how different components work “under the hood,” and how they communicate with each other. The detailed knowledge helps in implementing and maintaining high-throughput databases critical to your business and its customers. You’ll learn how to identify the root cause of each problem and understand how different design and implementation decisions affect performance of your systems. New in this second edition is coverage of SQL Server 2016 Internals, including In-Memory OLTP, columnstore enhancements, Operational Analytics support, Query Store, JSON, temporal tables, stretch databases, security features, and other improvements in the new SQL Server version. The knowledge also can be applied to Microsoft Azure SQL Databases that share the same code with SQL Server 2016. Pro SQL Server Internals is a book for developers and database administrators, and it covers multiple SQL Server versions starting with SQL Server 2005 and going all the way up to the recently released SQL Server 2016. The book provides a solid road map for understanding the depth and power of the SQL Server database server and teaches how to get the most from the platform and keep your databases running at the level needed to support your business. The book: • Provides detailed knowledge of new SQL Server 2016 features and enhancements • Includes revamped coverage of columnstore indexes and In-Memory OLTP • Covers indexing and transaction strategies • Shows how various database objects and technologies are implemented internally, and when they should or should not be used • Demonstrates how SQL Server executes queries and works with data and transaction log What You Will Learn Design and develop database solutions with SQL Server. Troubleshoot design, concurrency, and performance issues. Choose the right database objects and technologies for the job. Reduce costs and improve availability and manageability. Des

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值