我有这样的查询:
select dbo.fn_complexFunction(t.id)
from mytable t
在SQL Sentry Plan Explorer中,我注意到我必须运行Get Estimated Plan才能使查询计划包括UDF。
运行“获取实际计划”时,似乎逻辑读取和其他指标未包括UDF中发生的操作。在这种情况下,是否是使用Profiler的唯一解决方法?
我有这样的查询:
select dbo.fn_complexFunction(t.id)
from mytable t
在SQL Sentry Plan Explorer中,我注意到我必须运行Get Estimated Plan才能使查询计划包括UDF。
运行“获取实际计划”时,似乎逻辑读取和其他指标未包括UDF中发生的操作。在这种情况下,是否是使用Profiler的唯一解决方法?
Answers:
我们这里最大的问题是:
SET STATISTICS IO ON;
两者中的任何一个时都不会显示函数所引起的I / O (这是Table I/O
填充选项卡的方式)。考虑针对AdventureWorks2012的以下视图和功能。给定标题表中的随机行,这只是从明细表中返回随机行的愚蠢尝试-主要是确保每次都生成尽可能多的I / O。
CREATE VIEW dbo.myview
WITH SCHEMABINDING
AS
SELECT TOP (100000) rowguid, SalesOrderID, n = NEWID()
FROM Sales.SalesOrderDetail ORDER BY NEWID();
GO
CREATE FUNCTION dbo.whatever(@SalesOrderID INT)
RETURNS UNIQUEIDENTIFIER
WITH SCHEMABINDING
AS
BEGIN
RETURN
(
SELECT TOP (1) rowguid FROM dbo.myview
WHERE SalesOrderID = @SalesOrderID ORDER BY n
);
END
GO
Management Studio会(和不会)告诉您的内容
在SSMS中进行以下查询:
SET STATISTICS IO ON;
SELECT TOP (5) SalesOrderID, dbo.whatever(SalesOrderID)
FROM Sales.SalesOrderHeader ORDER BY NEWID();
SET STATISTICS IO OFF;
当您估计一个计划时,您将获得一个查询计划和一个函数的单一计划(而不是您希望的5个):
显然,您根本没有得到任何I / O数据,因为查询实际上并未执行。现在,生成一个实际计划。您将在结果网格中获得预期的5行,以下计划(这几乎没有提及UDF,除了XML,您可以将其作为查询文本的一部分和标量运算符的一部分找到):
和以下STATISTICS IO
输出(Sales.SalesOrderDetail
即使我们知道必须从该表中读取,也绝对不会提及):
表'SalesOrderHeader'。扫描计数1,逻辑读57,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
计划资源管理器告诉您什么
当PE为同一查询生成估计计划时,它知道与SSMS相同的内容。但是,它确实以更直观的方式显示事物。例如,外部查询的估计计划显示了函数的输出如何与查询的输出组合在一起,并且在单个计划图中立即清楚地看到两个表中都有I / O:
它还显示了功能的计划本身,为了完整起见,我仅将其包括在内:
现在,让我们来看一个实际的计划,它的实用性要高数千倍。同样,这里的缺点是,它仅具有SQL Server决定显示的信息,因此它只能公开SQL Server提供的图形化计划图。这不是有人决定不向您显示有用的东西的情况;基于提供的计划XML,它只是一无所知。在这种情况下,就像在SSMS中一样,您只能看到外部查询的计划,就好像根本没有调用该函数一样:
Table I / O选项卡也仍然依赖的输出STATISTICS IO
,该输出也忽略了在函数调用中执行的任何活动:
但是,PE会为您获取整个呼叫堆栈。我偶尔听到有人问:“ Pffft,我什么时候需要调用堆栈?” 好吧,您实际上可以分解每个函数调用所花费的时间,使用的CPU和读取次数(对于TVF,则是产生的行数):
不幸的是,您没有能力将其与I / O来自哪个表进行关联(再次,因为SQL Server不提供该信息),并且未使用UDF名称进行标记。 (因为它被捕获为一条临时语句,而不是函数调用本身)。但是,它确实使您看到(而Management Studio却看不到)您的UDF是一只狗。您仍然必须连接一些点,但是点较少,并且它们靠得更近。
关于探查器
最后,我强烈建议您不要使用Profiler,除非要设置要编写脚本的服务器端跟踪,然后在任何UI工具的范围之外运行。在生产系统上使用Profiler几乎肯定会引起比其解决的问题更多的问题。如果要获取此信息,请使用服务器端跟踪或扩展事件,并确保非常明智地进行过滤。即使没有事件探查器,跟踪也会影响您的服务器,并且通过扩展事件检索显示计划也不是世界上最有效的事情。