SentryOne Plan Explorer是否将UDF中的读数计数?


9

我有这样的查询:

select dbo.fn_complexFunction(t.id)
from mytable t

SQL Sentry Plan Explorer中,我注意到我必须运行Get Estimated Plan才能使查询计划包括UDF。

运行“获取实际计划”时,似乎逻辑读取和其他指标未包括UDF中发生的操作。在这种情况下,是否是使用Profiler的唯一解决方法?


1
据我所知,查询引擎本身并未考虑UDF中的读取。这是避免使用UDF的主要原因,因为UDF对优化器不透明。
JNK

Answers:


11

我们这里最大的问题是:

  1. 就像@JNK所说的那样,SQL Server混淆了UDF的使用,并且对它们进行了可怕的处理(就像总是估计一行)。当您在SSMS中生成实际计划时,您也完全看不到它的用途。计划资源管理器受到相同的限制,因为它只能提供有关SQL Server提供的计划的信息。
  2. 在生成实际计划时,该代码依赖于不同的运行时指标来源。不幸的是,计划XML不包括函数调用,并且SQL Server在使用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个):

Management Studio中的预估计划

显然,您根本没有得到任何I / O数据,因为查询实际上并未执行。现在,生成一个实际计划。您将在结果网格中获得预期的5行,以下计划(这几乎没有提及UDF,除了XML,您可以将其作为查询文本的一部分和标量运算符的一部分找到):

Management Studio中的实际计划

和以下STATISTICS IO输出(Sales.SalesOrderDetail即使我们知道必须从该表中读取,也绝对不会提及):

表'SalesOrderHeader'。扫描计数1,逻辑读57,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。

计划资源管理器告诉您什么

当PE为同一查询生成估计计划时,它知道与SSMS相同的内容。但是,它确实以更直观的方式显示事物。例如,外部查询的估计计划显示了函数的输出如何与查询的输出组合在一起,并且在单个计划图中立即清楚地看到两个表中都有I / O

计划浏览器中的估计计划

它还显示了功能的计划本身,为了完整起见,我仅将其包括在内:

计划资源管理器中UDF的估计计划

现在,让我们来看一个实际的计划,它的实用性要高数千倍。同样,这里的缺点是,它仅具有SQL Server决定显示的信息,因此它只能公开SQL Server提供的图形化计划图。这不是有人决定不向您显示有用的东西的情况;基于提供的计划XML,它只是一无所知。在这种情况下,就像在SSMS中一样,您只能看到外部查询的计划,就好像根本没有调用该函数一样

计划浏览器中的实际计划

Table I / O选项卡也仍然依赖的输出STATISTICS IO,该输出也忽略了在函数调用中执行的任何活动:

计划资源管理器中实际计划的表I / O

但是,PE会为您获取整个呼叫堆栈。我偶尔听到有人问:“ Pffft,我什么时候需要调用堆栈?” 好吧,您实际上可以分解每个函数调用所花费的时间,使用的CPU和读取次数(对于TVF,则是产生的行数)

计划管理器中的调用堆栈,显示UDF调用

不幸的是,您没有能力将其与I / O来自哪个表进行关联(再次,因为SQL Server不提供该信息),并且未使用UDF名称进行标记。 (因为它被捕获为一条临时语句,而不是函数调用本身)。但是,它确实使您看到(而Management Studio却看不到)您的UDF是一只狗。您仍然必须连接一些点,但是点较少,并且它们靠得更近。

关于探查器

最后,我强烈建议您不要使用Profiler,除非要设置要编写脚本的服务器端跟踪,然后在任何UI工具的范围之外运行。在生产系统上使用Profiler几乎肯定会引起比其解决的问题更多的问题。如果要获取此信息,请使用服务器端跟踪或扩展事件,并确保非常明智地进行过滤。即使没有事件探查器,跟踪也会影响您的服务器,并且通过扩展事件检索显示计划也不是世界上最有效的事情


啊,我不知道Pro版本中的调用堆栈。那正是我想要的。很高兴知道存在。在这一点上,我认为我无法证明价格合理,但我会在未来的情况下牢记这一价格。为什么有SQL Server不提供STATISTICS IO中UDF的I / O信息的原因?忽略这些基本信息是一种误导。
加布(Gabe)2013年

3
@Gabe我不知道原因,对不起。也许使咨询更有利可图?
亚伦·伯特兰

1
@gabe现在计划浏览器是完全免费的..它称为哨兵一号,具有所有pro +终极版功能-全部免费。
金莎(Kin Shah)2016年
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.