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

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

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

 1 -- Create a simple orders table
 2 CREATE TABLE Orders
 3 (
 4     OrderDate DATE NOT NULL,
 5     Col2 INT NOT NULL,
 6     Col3 INT NOT NULL
 7 )
 8 GO
 9
10 -- Create a Non-Unique Clustered Index on the table
11 CREATE CLUSTERED INDEX idx_CI ON Orders(OrderDate)
12 GO
13
14 -- Insert 31465 rows from the AdventureWorks2008r2 database
15 INSERT INTO Orders (OrderDate, Col2, Col3) SELECT OrderDate, CustomerID, TerritoryID FROM AdventureWorks2008R2.Sales.SalesOrderHeader
16 GO
17
18 -- Rebuild the Clustered Index, so that we get fresh statistics.
19 -- The last value in the Histogram is 2008-07-31.
20 ALTER INDEX idx_CI ON Orders REBUILD
21 GO
22
23 -- Insert 200 additional rows *after* the last step in the Histogram
24 INSERT INTO Orders (OrderDate, Col2, Col3)
25 VALUES (‘20100101‘, 1, 1)
26 GO 200

在索引重建后,我们再看下直方图,我们发现最后步进的值是2008-07-31。

1 DBCC SHOW_STATISTICS(‘dbo.Orders‘, ‘idx_CI‘) WITH HISTOGRAM

你已经看到,在最后步进到表里后,我们插入了200条额外记录。这样的话,直方图并没有真实反馈实际的数据分布情况,但SQL Server还是要进行基数计算。我们现在来看看在不同版本里SQL Server是如何处理这个问题的。

SQL Server 2005 SP1- SQL Server 2012

在SQL Server 2014之前,基数计算对此问题的处理非常简单:SQL Server估计行数为1,你可以从下面的图片里看到。

点击工具栏的显示包含实际的执行计划,并执行如下查询:

SELECT * FROM dbo.Orders WHERE OrderDate=‘2010-01-01‘

自SQL Server 2005 SP1起,查询优化器可以标记1列为自增长(Ascending)来克服刚才介绍的限制。如果你用自增长列值更新了统计信息对象3次,那列就会被标记为自增长列。为了看有没有列标记为自增长,你可以使用跟踪标记2388。当你启用这个跟踪标记,DBCC SHOW_STATISTICS的输出就改变了,有额外列返回。

DBCC TRACEON(2388)
DBCC SHOW_STATISTICS(‘dbo.Orders‘, ‘idx_CI‘)

现在下面的代码更新统计信息3次,每次用自增长键列值在我们聚集索引末尾插入行。

 1 -- => 1st update the Statistics on the table with a FULLSCAN
 2 UPDATE STATISTICS Orders WITH FULLSCAN
 3 GO
 4
 5 -- Insert 200 additional rows *after* the last step in the Histogram
 6 INSERT INTO Orders (OrderDate, Col2, Col3)
 7 VALUES (‘20100201‘, 1, 1)
 8 GO 200
 9
10 -- => 2nd update the Statistics on the table with a FULLSCAN
11 UPDATE STATISTICS Orders WITH FULLSCAN
12 GO
13
14 -- Insert 200 additional rows *after* the last step in the Histogram
15 INSERT INTO Orders (OrderDate, Col2, Col3)
16 VALUES (‘20100301‘, 1, 1)
17 GO 200
18
19 -- => 3rd update the Statistics on the table with a FULLSCAN
20 UPDATE STATISTICS Orders WITH FULLSCAN
21 GO

然后,当我们执行DBCC SHOW_STATISTICS命令,你会看到SQL Server已讲那列标记为Ascending。

DBCC TRACEON(2388)
DBCC SHOW_STATISTICS(‘dbo.Orders‘, ‘idx_CI‘)

现在当你再次执行查询不是直方图范围的数据时,没有任何改变。为了使用标记为自增长键列,你要启用另外一个跟踪标记-2389。如果你启用这个跟踪标记,查询优化器就是密度向量(Density Vector)来进行基数计算。

-- Now we query the newly inserted range which is currently not present in the Histogram.
-- With Trace Flag 2389, the Query Optimizer uses the Density Vector to make the Cardinality Estimation.
SELECT * FROM Orders
WHERE OrderDate = ‘20100401‘
OPTION (RECOMPILE, QUERYTRACEON 2389)
GO

来看下现在的表密度:

DBCC TRACEOFF(2388)
DBCC SHOW_STATISTICS(‘dbo.Orders‘, ‘idx_CI‘)

现在的表密度是0.0008873115,因此查询优化器的估计行数是28.4516:0.0008873115*(32265-200)。

这虽然不是最好的结果,但比估计行数1好很多!

(这里有问题,我本地是SQL Server 2008r2,测试估计行数还是1,不知原因,望知道的朋友解释下,多谢!

)

SQL Server 2014

在SQL Server 2014引入的一个新功能是新基数计算。新基数计算对于自增长键问题的处理非常简单:默认不使用任何跟踪标记,来使用统计信息对象的密度向量来进行基数计算。下面查询启用2312跟踪标记的基数计算来运行同个查询。

1 -- With the new Cardinality Estimator SQL Server estimates 28.4516 rows at the Clustered Index Seek operator.
2 SELECT * FROM Orders
3 WHERE OrderDate = ‘20100401‘
4 OPTION (RECOMPILE, QUERYTRACEON 2312)
5 GO

我们来看这里的基数计算,你会看到查询优化器再次估计行数是28.4516,但这一次没表上自增长。这是SQL Server 2014的自带功能。

(SQL Server 2014测试失败,估计行数也是1……)

小结

在这篇文章,我向你展示了SQL Server的查询优化器如何处理自增长键问题。在SQL Server 2014之前,你需要启用2389跟踪标记来获得更好的基数计算——这样的话那列会标记为自增长(ascending)。SQL Server 2014,查询优化器默认就使用密度向量来进行基数计算,这样就方便很多。我希望你对此有所收获,在SQL Server里如何处理自增长键列问题你会有更好的想法。

感谢关注!

时间: 2024-10-14 08:54:18

使用自增长键列值的统计信息的相关文章

UNIQUEIDENTIFIER列上的统计信息

UNIQUEIDENTIFIER列上的统计信息非常有意思,在它上面有一些很令人讨厌的行为.我们来看下. 问题重现(The repro) 为了向你展示我们刚抱怨的行为,我用下列简单的表定义创建了一个数据库,我在UNIQUEIDENTIFIER列上强制主键约束.这意味着SQL Server在后台会生成唯一聚集索引,聚集索引本身有一个统计信息对象来描述那列的数据分布情况.当然,数据分布是线性的,因为在UNIQUEIDENTIFIER列每个值本身都是唯一的. 1 -- Create a new tabl

关于odoo tree 视图 数值类型的列值 的统计

odoo的tree视同中  可以在每页的最后一列显示该页数的的某一个数值类型的列的数据总数 例如: 图示:重量就是一个数值类型的列   我们可以在 每页的最后显示该列的总数 如: 箭头所示的就是该列的总数 代码如下:在tree视图中增加: <field name="qty" sum="Qty"/> sum  就是计算该列总数的插件     可能还有计算平均数之类的,但是还没有去尝试

索引深入浅出(10/10):创建索引时,键列位置的重要性

在过去的文章里,我们已经讨论了各种不同索引.这个文章里,我们会讨论下键列的顺序(索引列的顺序).索引键列的顺序基于数据的访问模式还有你想如何组织数据. 对于索引键列的顺序,常规指导方针就是把查询用到最多的列放在第一列.这并不是说,所有你索引里的唯一ID列就应该是第一列.优化器是基于索引上的可用统计信息来选择索引的.统计信息会给你键列的使用密度信息,即索引的唯一性,直方图(histogram )用来存储那一列值分布情况信息. 让我们用customer表做例子,它保存来自各个国家的客户信息. 1 C

oracle里表、索引、列的统计信息

一.表的统计信息 表的统计信息用于描述表的详细信息,包括记录数(num_rows).表块的数量(blocks).平均行长度(avg_row_len)等典型维度.这些维度可以通过数据字典表DBA_TABLES.DBA_TAB_PARTITIONS和DBA_TAB_SUBPARTITIONS来分别查看表.分区表的分区和分区表的子分区的统计信息. 二.索引的统计信息 索引的统计信息描述了索引的详细信息,它包含了索引的层级(blevel).叶子块数量(leaf_blocks).聚簇因子(clusteri

SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)

本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. 今天来写一下统计信息对于复合索引在预估时候的计算方法和潜在问题. 本文原形来自于是个实际业务问题,某SQL在利用一个符合索引做查询的时候,发现始终会出现预估误差较大的情况, 而改变复合索引的列顺序,这个预估行数的误差会发生变化, 也就是说,Create  index idx_index1 ON T

翻译之: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

数据库性能优化、统计信息与对象统计信息概述收集、扩展统计信息、dbms_stats.get_prefs

数据库性能优化 相关书籍: 1.基于成本的Oracle优化法则 2.Oracle性能诊断艺术 3.基于Oracle的SQL优化 ----------------------------------------------------------------------------------------- 两种优化器: CBO  cost-base optimizer 基于cost 更大适应性/灵活性/10g开始 RBO  rule-base optimizer 基于规则 制定了15条/10g以

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

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

ORACLE 收集统计信息

原文链接:http://blog.itpub.net/2317695/viewspace-1226138/ 今天网上看到一篇关于收集统计信息的文章,还不错,特转载下来. 1.     理解什么是统计信息 优化器统计信息就是一个更加详细描述数据库和数据库对象的集合,这些统计信息被用于查询优化器,让其为每条SQL语句选择最佳的执行计划.优化器统计信息包括: ·         表的统计信息 o   行数 o   Block数 o   行平均长度 ·         列的统计信息 o   列中不同值的