教你如何看懂SQL Server查询计划(4)
还是来看看这个【执行过程表格】吧。我来挑几个重要的说一下。
【Rows】:表示在一个执行步骤中,所产生的记录条数。(真实数据,非预期)
【Executes】:表示某个执行步骤被执行的次数。(真实数据,非预期)
【Stmt Text】:表示要执行的步骤的描述。
【EstimateRows】:表示要预期返回多少行数据。
在这个【执行过程表格】中,对于优化查询来说,我认为前三列是比较重要的。对于前二列,我上面也解释了,意思也很清楚。前二列的数字也大致反映了那些步骤所花的成本,对于比较慢的查询中,应该留意它们。【Stmt Text】会告诉你每个步骤做了什么事情。对于这种表格,它所要表达的其实是一种树型信息(一行就表示在图形方式下的一个节点),所以,我建议从最内层开始去读它们。做为示例,我来解释一下这张表格它所表达的执行过程。
第5行:【Clustered Index Seek(OBJECT:([MyNorthwind].[dbo].[Customers].[PK_Customers]), SEEK:([MyNorthwind].[dbo].[Customers].[CustomerID]=[MyNorthwind].[dbo].[Orders].[CustomerID]) ORDERED FORWARD)】,意思是说,SQL Server在对表Customers做Seek操作,而且是按照【Clustered Index Seek】的方式,对应的索引是【PK_Customers】,seek的值来源于[Orders].[CustomerID]
第4行:【Clustered Index Scan(OBJECT:([MyNorthwind].[dbo].[Orders].[PK_Orders]), WHERE:([MyNorthwind].[dbo].[Orders].[OrderDate]>='2010-12-01 00:00:00.000' AND [MyNorthwind].[dbo].[Orders].[OrderDate]<'2011-12-01 00:00:00.000'))】,意思是说,SQL Server在对表Customers做Scan操作,即:最差的【表扫描】的方式,原因是,OrderDate列上没有索引,所以只能这样了。
第3行:【Nested Loops(Left Outer Join, OUTER REFERENCES:([MyNorthwind].[dbo].[Orders].[CustomerID]))】,意思是说,SQL Server把第5行和第4行产生的数据用【Nested Loops】的方式联接起来,其中Outer表是Orders,要联接的匹配操作也在第5行中指出了。
第2行:【Compute Scalar(DEFINE:([Expr1006]=isnull([MyNorthwind].[dbo].[Customers].[CustomerName],N'')))】,意思是说,要执行一个isnull()函数的调用。具体原因请参考本文前部分中给出视图定义代码。
第1行:【SELECT [v].[OrderID],[v].[CustomerID],[v].[CustomerName],[v].[OrderDate],[v].[SumMoney],[v].[Finished] FROM [OrdersView] [v] WHERE [v].[OrderDate]>=@1 AND [v].[OrderDate]<@2】,通常第1行就是整个查询,表示它的返回值。
索引统计信息:查询计划的选择依据
前面一直说到【执行计划】,既然是计划,就表示要在具体执行前就能确定下来的操作方案。那么SQL Server是如何选择一个执行计划的呢?SQL Server怎么知道什么时候该用索引或者用哪个索引呢?对于SQL Server来说,每当要执行一个查询时,都要首先检查这个查询的执行计划是否存在缓存中,如果没有,就要生成一个执行计划,具体在产生执行计划时,并不是看有哪些索引可用(随机选择),而是会参考一种被称为【索引统计信息】的数据。如果您仔细地看一下前面的执行计划或者执行过程表格,会发现SQL Server能预估每个步骤所产生的数据量,正是因为SQL Server能预估这些数据量,SQL Server才能选择一个它认为最合适的方法去执行查询过程,此时【索引统计信息】就能告诉SQL Server这些信息。说到这里,您是不是有点好奇呢,为了让您对【索引统计信息】有个感性的认识,我们来看看【索引统计信息】是个什么样子的。请在【SQL Server Management Studio】,输入以下语句,然后执行。
dbcc show_statistics (Products, IX_CategoryID)
得到的结果如下图:
首先,还是解释一下命令:【dbcc show_statistics】这个命令可以显示我们想知道的【索引统计信息】,它需要二个参数,1. 表名,2. 索引名
再来看看命令的结果,它有三个表格组成:
1. 第一个表格,它列出了这个索引统计信息的主要信息。
列名 说明Name统计信息的名称。Updated上一次更新统计信息的日期和时间。Rows表中的行数。Rows Sampled统计信息的抽样行数。Steps数据可分成多少个组,与第三个表对应。Density第一个索引列前缀的选择性(不包括 EQ_ROWS)。Average key length所有索引列的平均长度。String Index如果为“是”,则统计信息中包含字符串摘要索引,以支持为 LIKE 条件估算结果集大小。仅适用于 char、varchar、nchar 和 nvarchar、varchar(max)、nvarchar(max)、text 以及 ntext 数据类型的前导列。
2. 第二个表格,它列出各种字段组合的选择性,数据越小表示重复越性越小,当然选择性也就越高。