执行计划与STATISTICS IO顺序


20

SQL Server图形执行计划从右到左,从上到下阅读。产生的输出是否有意义SET STATISTICS IO ON

以下查询:

SET STATISTICS IO ON;

SELECT  *
FROM    Sales.SalesOrderHeader AS soh
        JOIN Sales.SalesOrderDetail AS sod ON soh.SalesOrderID = sod.SalesOrderID
        JOIN Production.Product AS p ON sod.ProductID = p.ProductID;

生成此计划:

图形化执行计划

STATISTICS IO输出:

Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'SalesOrderDetail'. Scan count 1, logical reads 1246, physical reads 3, read-ahead reads 1277, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'SalesOrderHeader'. Scan count 1, logical reads 689, physical reads 1, read-ahead reads 685, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 1, logical reads 15, physical reads 1, read-ahead reads 14, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

因此,我重申:有什么用?是否有有意义的STATISTICS IO输出顺序或使用了任意顺序?

Answers:


9

我最初对各种查询的研究表明根本没有任何模式,但是在仔细关注之后,对于串行计划来说似乎是可以预测的。我结束于KB314648,@ AustinZellner提到:

每个SQL Server连接都有一个关联的进程状态结构(PSS),用于维护特定于连接的状态信息。sysprocesses系统表中的每个唯一服务器进程ID(SPID)代表一个不同的PSS,并且sysprocesses虚拟表中的信息是对该状态信息的“查看”。

和与您的问题有关的部分:

如果为连接启用了STATISTICS IO,则SQL Server在查询执行期间分配一个数组,以按表跟踪IO信息。当SQL Server处理查询时,它将在该数组的适当表的条目中记录对页面的每个逻辑请求,以及该逻辑IO请求是否导致物理IO。SQL Server在查询结束时在错误消息3615中返回信息。

观察到的行为表明,将按照生成IO的顺序对数组进行输入,这实际上是物理运算符上GetNext()的结果。统计信息输出中的最后一个条目是导致记录IO的第一个表,第一个条目是最后一个表。我推测并行计划的顺序是不可预测的(或更难以预测),因为无法保证首先安排哪个并行任务。


5

在我看来,这是计划中数据读取访问的相反顺序。您的计划将首先从Product表中读取以构建哈希表(工作表)。它比从SalesOrderHeader读取,并形成SalesOrderDetail并将它们与合并联接运算符结合在一起。然后从最后读取工作表,以将原始产品行与合并联接中的行进行哈希匹配。这与它们在统计信息输出中列出的顺序完全相反。

但是,我不知道有任何文档会对此进行指定。如果要确定按什么顺序进行表访问,请阅读执行计划。


在这种情况下,它以相反的顺序出现,在其他情况下则不同。我怀疑,如果没有对引擎的深入了解,就不会发现任何通常不向公众提供的命令。
耶利米·佩斯卡

您是否有一个示例,说明其顺序不同?
塞巴斯蒂安·梅因

SELECT * FROM Sales.SalesOrderHeader AS soh JOIN Sales.SalesOrderDetail AS sod ON soh.SalesOrderID = sod.SalesOrderID LEFT JOIN Sales.SalesPerson AS sp ON ON soh.SalesPersonID = sp.BusinessEntityID LEFT JOIN Person.Person AS p2 ON sp.BusinessEntityID = p2 .BusinessEntityID加入Production.Product AS on on sod.ProductID = p.ProductID;
耶利米·佩斯卡

只要不涉及并行性,我的观察就成立。您可以使用TOP(100),TOP(1000)和TOP(10000)运行查询以查看串行计划。但是,使用TOP(100000)或不使用TOP时,您会得到两个不同的并行计划,并且所有赌注似乎都没有了。
塞巴斯蒂安·梅因

3

我一直认为这是有条理的,从那时起我做的编程多于管理。我经历了一些执行计划,并仔细检查了我的信念。

这是我看到的:

在多步骤查询(例如我们的许多存储过程)中,顺序反映了运行查询的物理顺序。

对于特定查询,统计信息IO似乎通过报告从右至左的统计信息来反映执行计划。

也许这更是一种观察。


2
可能是这个东西。反转表中的顺序SELECT COUNT(*) FROM HumanResources.EmployeeDepartmentHistory UNION ALL SELECT COUNT(*) FROM HumanResources.Employee UNION ALL SELECT COUNT(*) FROM HumanResources.Department也会反转IO输出,但不能解释为什么在问题示例中首先报告工作表。
马丁·史密斯,

@MartinSmith是的,从我有限的角度来看,工作台是通配符。
RLF 2013年

0

因此,我认为统计信息io的结果可以更深入地了解运行时实际发生的情况,因为它将考虑并受需要从磁盘读取而不是从缓存读取的影响,并且还受帐户权限的影响正在运行查询。然后,表格在统计信息返回中的位置会受到除探查器所考虑的因素以外的其他因素的影响。

这是一篇提供相关见解和示例的kb文章:http : //support.microsoft.com/kb/314648


1
问题不STATISTICS IO在于一般的输出。纯粹是关于报告读取各个表的顺序。在您的链接中我没有看到任何关于此的信息。
马丁·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.