第13/24周 统计信息

欢迎来到性能调优培训的第4个月。这个月全是关于SQL Server里的统计信息,还有它们如何帮助查询优化器生成足够好的执行计划。统计信息主要是被查询优化器用来估计查询返回的行数。它只是个估计,没别的。

统计信息概述

SQL Server使用在统计信息对象里称作直方图(Histogram)的东西,它描述了对于所给列最大200步长(Steps)的数据分布情况。最大的局限性之一,对于SQL Server里的统计信息是200步长的局限性(使用过滤统计信息可以超过这个步长,这在SQL Server 2008里就引入了)。

另外的局限性是统计信息的自动更新(Auto Update)机制:对于大于500行的表,如果500+20%的列值发生改变,统计信息才会更新。这就意味着,一旦表增长,你的统计信息的自动更新频率将越少(每次触发自动更新需要更多的记录修改)。

假设你有100000条记录的表,这个情况下,如果修改了20500(20%+500)的数据,统计信息才会自动更新。如果你有1000000条记录的表,你需要修改200500(20%+500)的数据,统计信息才会自动更新。这里用到的算法是指数的,不是线性的。在SQL Server里有2371的跟踪标志(trace flag)也会影响这个行为。

当你的执行计划里保航书签查找时,这个行为就会是巨大的问题。正如你知道的,基于当前的统计信息,如果查询的估计行数是非常少的,查询优化器才会选择书签查找运算符。如果你的统计信息过期,你的执行计划还是有效的话,SQL Server就会盲目重用缓存计划,你的页读取就会暴涨。我们来看看这个问题的具体例子。

失真的统计信息(Stale Statistics)

下面的脚本会创建有1500条记录的表,在column2列有平均的数据分布。另外我们在column2列上定义非聚集索引。

 1 CREATE TABLE Table1
 2 (
 3    Column1 INT IDENTITY,
 4    Column2 INT
 5 )
 6 GO
 7
 8 -- Insert 1500 records into Table1
 9 SELECT TOP 1500 IDENTITY(INT, 1, 1) AS n INTO #Nums
10 FROM
11 master.dbo.syscolumns sc1
12
13 INSERT INTO Table1 (Column2)
14 SELECT n FROM #nums
15
16 DROP TABLE #nums
17 GO
18
19 CREATE NONCLUSTERED INDEX idx_Table1_Colum2 ON Table1(Column2)
20 GO

当你对表进行简单的SELECT * 查询时,你会得到带有书签查找运算符的执行计划:

1 SELECT * FROM dbo.Table1 WHERE Column2=‘9‘

索引查找(Non Clustered)运算符可以看到,SQL Server估计行数是1(估计行数(Estimated Number of Rows)属性),实际上SQL Server也处理1条记录(实际行数(Actual Number of Rows)属性)。这就是说,我们这里用到的统计信息是准确的,查询本身产生3个逻辑读。

我们现在的表有1500条记录,因此当20% + 500条记录发生改变时,SQL Server会自动更新非聚集索引的统计信息。算一下,我们需要修改800条数据(1500 * 20% + 500)。

接下来我们对表做如下处理:我们对SQL Server做一点动作,只插入799条新记录。但799条记录的第2列值都是2。这就是说我们完全改变第2列的平均数据分布。统计信息会认为只有1条第2列值为2的记录返回,但实际上却有800条记录返回(1条已存在的,799条新插入的):

1 SELECT TOP 799 IDENTITY(INT, 1, 1) AS n INTO #Nums
2 FROM
3 master.dbo.syscolumns sc1
4
5 INSERT INTO Table1 (Column2)
6 SELECT 2 FROM #nums
7
8 DROP TABLE #nums
9 GO

现在我们来执行下列查询语句,找第2列值为2的记录,并打开执行计划显示和IO统计。

1 SET STATISTICS IO ON
2 SELECT * FROM dbo.Table1 WHERE Column2 =‘2‘

SQL Server重用了有书签查找的执行计划。这就是说执行计划里的书签查找执行了1500次——一次性对所有记录!这会耗费大量的逻辑读——SQL Server这里报告了806个页读取。

从图中可以看到,实际行数(Actual Number of Rows)现在已经远远超过了估计行数(Estimated Number of Rows)

SQL Server里失真的统计信息就会带来这样的问题。

小结

今天的性能调优培训我给你简单介绍了SQL Server里的统计信息。如你所见,失真的统计信息,对于缓存的,重用的执行计划会带来严重的性能问题。

我希望现在你已经能很好的理解SQL Server里的统计信息,当它们过期是,会给你的执行计划带来副作用。下周我会进一步讨论统计信息,还有在SQL Server内部它们是怎样的。请继续关注。

时间: 2024-10-29 19:11:07

第13/24周 统计信息的相关文章

第13/24周 直方图和密度向量

欢迎回到性能调优培训.今天我想详细谈下统计信息在SQL Server内部是如何呈现的.假设有这样的问题:执行计划里的某个运算符的估计行数是42,但你知道对于这个查询,42不是正确的答案.但是你怎么来解读统计信息来理解这个估计是从哪里来的?我们来谈论下直方图(Histogram)和密度向量(Density Vector). 直方图(Histogram) 首先我们来看下直方图.直方图的用途是用高效.压缩的方式存储列数据分布情况.每次当你在表上创建索引时(聚集/非聚集索引),SQL Server会为你

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.

第24/24周 数据库维护(Database Maintenance)

哇哦,光阴似箭!欢迎回到性能调优培训的最后一期.今天我会详细讲下SQL Server里的数据库维护,尤其是索引维护操作,还有如何进行数据库维护. 索引维护 作为一个DBA,数据库维护是你工作中非常重要的一部分,让数据库获得最佳性能.一个SQL Server数据库就像一辆车:它需要经常的检查来保证运行没有问题,副作用,且拥有最大可能的性能.SQL Server数据库最重要的部分是它的索引及其对应的统计信息对象.SQL Server运行一段时间后会有索引碎片,统计信息必须更新,这样的话查询优化器才可

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

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

mysql5.6的统计信息

mysql5.6对统计信息进行了改善,使得使用innodb存储引擎的数据表的统计信息可以永久(persistent)管理.从5.6开始,在mysql数据库的innodb_index_stats表和innodb_table_stats表中也可以访问索引. root@localhost:mysql3316.sock 09:06:19 [mysql]>show tables like "%_stats"; +---------------------------+ | Tables_i

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

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

10G之后统计信息收集后为什么执行计划不会被立马淘汰

在10G之前,使用DBMS_STATS收集统计信息将会导致与此对象相关的游标失效,下次执行此 的时候将会进行HARD PARSE,除非收集的时候NO_INVALIDATE设置为TRUE. 由于硬解析会消耗大量的CPU,还会导致大量的library cache 和 shared pool 的LATCH竞争,因此 如果由于统计信息收集导致大量的的游标失效,可能会带来HARD PARSE风暴,造成系统的负担. 但是如果采用NO_INVALIDATE=TRUE的方法,由于游标不失效,游标无法利用到新的统

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

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

SQL Server研究之统计信息—发现过期统计信息并处理详解

 前言: 统计信息是关于谓词中的数据分布的主要信息源,如果不知道具体的数据分布,优化器不能获得预估的数据集,从而不能统计需要返回的数据. 在创建列的统计信息后,在DML操作如insert.update.delete后,统计信息就会过时.因为这些操作更改了数据,影响了数据分布.此时需要更新统计信息. 在高活动的表中,统计信息可能几个小时就会过时.对于静态表,可能几个星期才会过时.这要视乎表上DML的操作. 从2000开始,SQLServer对增删改操作会增加在表sysindexes中的RowM