原文:http://sqlblog.com/blogs/ben_nevarez/archive/2009/09/03/how-the-query-optimizer-uses-statistics.aspx
备注:翻译不当,请指出或参考原文。
本文介绍了查询优化器在优化时如何使用统计来估计表达式的选择性,与使用“本地变量”的方式猜测表达式的选择性相比,查询优化器采用探测参数值的方式略显一筹。
注意:本文并未过多地介绍与之相关主题的其他细节,仅列举出一些简单的示例对查询优化器创建、使用统计进行描述。
首先启动SQL Server Management Studio并切换到AdventureWorks数据库,运行以下命令显示Sales.SalesOrderDetail表中ProductID列的当前统计信息:
dbcc show_statistics('Sales.SalesOrderDetail', IX_SalesOrderDetail_ProductID)
该命令的输出结果显示了主题、密度及统计对象的histogram。
1)了解histogram
首先介绍histogram步值的含义,先看步值为86的行,如下所示:
![clip_image002 clip_image002](http://sqlblog.com/blogs/ben_nevarez/clip_image002_thumb_5E0F110E.jpg)
select ProductID, COUNT(*) as Total查询结果如下:
from Sales.SalesOrderDetail
where ProductID between 827 and 831
group by ProductID
2)查询优化器知道值
select * from Sales.SalesOrderDetail
where ProductID = 831
select * from Sales.SalesOrderDetail
where ProductID = 828
这一次,这个值在步值为86的范围内,并且828不是RANGE_HI_KEY,故查询优化器使用AVG_RANGE_ROWS计算的列,其实,查询ProductID为829的记录,估计的行数也是36.6667,即使没有满足829条件的记录也是如此。
下面我们再来看一个不等的运算,试一下找出小于714的行数,也可以通过步值1到7的RANGE_ROWS和EQ_ROWS计算出(13223行)
下面看一下在执行计划中显示的估计行数:
select * from Sales.SalesOrderDetail
where ProductID < 714
declare @pid int = 897
select * from Sales.SalesOrderDetail
where ProductID = @pid
declare @pid int = 897
select * from Sales.SalesOrderDetail
where ProductID < @pid
与先前一样,此处与897无关,使用任何值都将得到相同的估计个数,对于不等运算来说,估计的行数约为总行数的30%,在本例为即为
121317*30%=36395.1。