我有这样的查询:
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 是唯一的解决方法吗?
我们这里最大的问题是:
SET STATISTICS IO ON;
任何一个时产生的 I/O(这就是Table I/O
选项卡的填充方式)。考虑以下针对 AdventureWorks2012 的视图和函数。这只是一个愚蠢的尝试,在给定标题表中的随机行的情况下,从详细信息表中返回随机行 - 主要是为了确保我们每次都生成尽可能多的 I/O。
Management Studio 会(和不会)告诉您的内容
在 SSMS 中执行以下查询:
当你估计一个计划时,你会得到一个查询计划和一个函数计划(不是你可能希望的 5 个):
显然,您根本得不到任何 I/O 数据,因为实际上并未执行查询。现在,生成一个实际的计划。您在结果网格中获得了预期的 5 行,以下计划(绝对没有明显提及 UDF,除了在 XML 中您可以找到它作为查询文本的一部分和标量运算符的一部分):
以及以下
STATISTICS IO
输出(完全没有提及Sales.SalesOrderDetail
,即使我们知道它必须从该表中读取):Plan Explorer 告诉您什么
当 PE 为同一查询生成估计计划时,它知道的事情与 SSMS 相同。然而,它确实以一种稍微更直观的方式显示事物。例如,外部查询的估计计划显示了函数的输出如何与查询的输出相结合,并且立即清楚 - 在单个计划图中 - 两个表都有 I/O:
它还单独显示了函数的计划,我只是为了完整性才包括在内:
现在,让我们来看看一个实际的计划,它的用处要大上千倍。这里的缺点是,同样,它只有 SQL Server 决定显示的信息,因此它只能公开 SQL Server 提供的图形计划图。这不是某人决定不向您展示有用的东西的情况;根据提供的计划 XML,它只是一无所知。在这种情况下,就像在 SSMS 中一样,您只能看到外部查询的计划,就好像根本没有调用该函数一样:
表 I/O 选项卡也仍然依赖于 的输出
STATISTICS IO
,它也忽略函数调用中执行的任何活动:但是,PE 会为您获取整个调用堆栈。我偶尔会听到有人问,“Pffft,我什么时候需要调用堆栈?” 好吧,您实际上可以分解每个函数调用所花费的时间、使用的 CPU 和读取次数(对于 TVF,还包括生成的行数) :
不幸的是,您无法将它关联回 I/O 来自哪个表(同样,因为 SQL Server 不提供该信息),并且它没有标有 UDF 名称(因为它被捕获为临时语句,而不是函数调用本身)。但是它让您看到的是您的 UDF 是什么狗,而 Management Studio 没有。您仍然需要加入一些点,但点数较少,而且它们靠得更近。
关于探查器
最后,我强烈建议远离 Profiler,除非它是为了设置您要编写脚本的服务器端跟踪,然后在任何 UI 工具的范围之外运行。对生产系统使用 Profiler 几乎肯定会导致比它解决的问题更多的问题。如果您想获取此信息,请使用服务器端跟踪或扩展事件,并确保非常明智地进行过滤。即使没有分析器,跟踪也会影响您的服务器,并且通过扩展事件检索显示计划也不是世界上最有效的事情。