最近被一个客户问到了这样一个有趣的问题——执行计划在生成过程中使用了那些统计信息呢?针对这个问题,客户也做了一些研究,并给了我下面两篇博文作为切入点。
1.&">nbsp; How to Find the Statistics Used to Compile an Execution Plan (http://sqlblog.com/blogs/paul_white/archive/2011/09/21/how-to-find-the-statistics-used-to-compile-an-execution-plan.aspx)
2. Statistics used in a cached query plan (http://blogfabiano.com/2012/07/03/statistics-used-in-a-cached-query-plan/)
在查看了这两篇博文后,我把其中的奥秘摘出来跟大家分享一下。
第一篇博文介绍了两个Trace Flag, 9204和9292。这两个Trace Flag是这样解释的:
9204 – 打印出被加载的统计信息
9292 – 打印出从元数据中得到的统计信息的头信息
当然,要看到这些信息,我们还需要打开Trace Flag 3604才能让这些显示出来。以下面的脚本为例,
USE Northwind GO DBCC FREEPROCCACHE() GO DBCC TRACEON(3604, 9292, 9204) GO SELECT Employees.FirstName, COUNT(Orders.OrderID) FROM Orders INNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID WHERE Employees.FirstName = '820.html">Steven' GROUP BY Employees.FirstName GO
其返回结果为:
Stats header loaded: DbName: Northwind, ObjName: Orders, IndexId: 4, ColumnName: EmployeeID, EmptyTable: FALSE Stats loaded: DbName: Northwind, ObjName: Orders, IndexId: 4, ColumnName: EmployeeID, EmptyTable: FALSE Stats header loaded: DbName: Northwind, ObjName: Orders, IndexId: 5, ColumnName: EmployeeID, EmptyTable: FALSE Stats header loaded: DbName: Northwind, ObjName: Employees, IndexId: 1, ColumnName: EmployeeID, EmptyTable: FALSE Stats loaded: DbName: Northwind, ObjName: Employees, IndexId: 1, ColumnName: EmployeeID, EmptyTable: FALSE Stats header loaded: DbName: Northwind, ObjName: Employees, IndexId: 4, ColumnName: FirstName, EmptyTable: FALSE Stats loaded: DbName: Northwind, ObjName: Employees, IndexId: 4, ColumnName: FirstName, EmptyTable: FALSE FirstName ---------- -----------Steven 42
从这个SELECT语句中,我们不难看出查询结果应该是员工Steven的First Name和这个员工有的所有的订单Order的数量。表Employees和Orders是用过EmployeeID来联系起来的。所以,在Employees.EmployeeID和Orders.EmployeeID上建立的索引上面的统计信息会被用来产生执行计划。当然除了他们,还应该有在字段Employees.FirstName上的统计信息,因为这个字段上没有索引存在,所以系统会在这里自动生成一个统计信息。
需要注意的是,Trace Flag 9204和9292 只会在这个SELECT语句第一次被编译的时候打印出这些统计信息的记录。如果执行计划已经存在于缓存中,那么这些统计信息的记录则不会被打印出来。只有在用DBCC FREEPROCCACHE(plan_handle)清理了这条语句的缓存计划后,再次执行的时候才会再次被打印出来。
第二篇博文介绍了另一个Trace Flag,8666。这个Trace Flag是这样解释的:
8666 – 将Showplan的详细信息打印出来
这个Trace Flag会将一些关于统计信息的内部信息显示出来。例如,
USE Northwind GO DBCC FREEPROCCACHE() GO DBCC TRACEON(8666) GO SELECT Employees.FirstName, COUNT(Orders.OrderID) FROM Orders INNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID WHERE Employees.FirstName = 'Steven' GROUP BY Employees.FirstName GO