欢迎回到 性能调优培训 。 今天我想详细谈下统计信息在SQL Server内部是如何呈现的。假设有这样的问题:执行计划里的某个运算符的估计行数是42,但你知道对于这个查询,42不是正确的答案。但是你怎么来解读统计信息来理解这个估计是从哪里来的?我们来谈论下直方图(Histogram)和密度向量(Density Vector)。
首先我们来看下直方图。直方图的用途是用高效、压缩的方式存储列数据分布情况。每次当你在表上创建索引时(聚集/非聚集索引),SQL Server会为你自动创建统计信息。这个统计信息就包含了那列(索引键)的数据分布信息。比如你有一个订单表,里面有个Country列,这列里有很多国家名字。因此直方图就是对这些国家个数分布情况的可视化:
在直方图里,我们用很多柱条描述数据分布情况:柱条越高,那列的这个值就记录数就越多。SQL Server使用同样的概念和格式来描述数据分布情况。我们通过一个例子来详细了解下。在 AdventureWorks2008R2 数据库里,我们找到表 SalesOrderDetail 里的 ProductID 列。这ProductID列存储着具体的销售产品ID信息。可以看到,ProductID列也有索引定义,那就说有对应的统计信息来描述ProductID列的数据分布情况。
在SSMS里,你通过查看表属性来查看列和统计信息,也可以使用 DBCC SHOW_STATISTICS 命令在结果里输出统计信息。
1 -- Show the statistics for a given index 2 DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail', IX_SalesOrderDetail_ProductID) 3 GO
从上图可以看到,这个命令返回3个不同的记录集:
如果你想详细了解这部分的统计信息是如何用来做参数预估的,可以看下 统计信息内幕:直方图和密度向量 。
我们再来看看神秘的密度向量,看下非聚集索引 IX_SalesOrderDetail_ProductID ,这个索引只在 ProductID 列建立。但是每个非聚集索引,SQL Server在索引的页层也保存聚集键作为逻辑指针。当你定义了非唯一的非聚集索引,聚集键也是非聚集索引导航结构的一部分。表里的聚集键 SalesOrderID 是个组合列,包含 SalesOrderID 列和 SalesOrderDetailID 列。
这就是说我们的非唯一非聚集索引事实上包含 ProductID , SalesOrderID 和 SalesOrderDetailID 列。索引键是个组合键。同样SQL Server需要为其他列创建密度向量,因为只有第1列( ProductID )是直方图里有信息,这个在上一部分我们已经看过了。当你看用 DBCC SHOW_STATISTICS 命令的输出时,密度向量是第2个表信息。
SQL Server在这里存储选择率(selectivity),不同列组合的密度。例如, ProductID 列的All density值是0.003759399,你可以用下列语句来验证下:
1 -- The "All Density" value for the column ProductID: 0,0037593984962406015 2 SELECT 1 / CAST(COUNT(DISTINCT ProductID) AS NUMERIC(18, 2)) FROM Sales.SalesOrderDetail 3 GO
对于 ProductID , SalesOrderID 组合列和 ProductID , SalesOrderID , SalesOrderDetailID 组合列的All density值分别是8.242868E-06和8.242868E-06。你可以用1除以2个组合列的唯一值来验证下。这里我们的记录是121317,这些聚集值( SalesOrderID , SalesOrderDetailID 组成了聚集键)都是唯一的,我们可以计算下:1/121317=8.242867858585359e-6。
在参数预估期间,SQL Server如何使用这个信息,详细可以点击刚才提到的 统计信息内幕:直方图和密度向量 。
今天你看到SQL Server内部是如何构建统计信息的。这里最重要的是 直方图(Histogram) 和 密度向量(Density Vector) ,它们一直是用来做参数预估的。希望这次 性能调优培训 你有所收获。
你可以阅读下面文章,加深对统计信息的理解:
理解统计信息(1/6):密度向量
理解统计信息(2/6):直方图
理解统计信息(3/6):谁创建和管理统计信息?在性能调优中,统计信息的作用
理解统计信息(4/6):自动更新统计信息的阀值——人为更新统计信息的重要性
理解统计信息(5/6):如何检测过期的统计信息
理解统计信息(6/6):统计信息汇总贴
统计信息内幕:直方图和密度向量
下周我们继续讨论在SQL Server里使用参数预估(cardinality estimation)的局限性,还有如何解决它们。到时候见!