转载

第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'

第13/24周 统计信息

第13/24周 统计信息

索引查找(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个页读取。

第13/24周 统计信息

第13/24周 统计信息

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

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

小结

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

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

正文到此结束
Loading...