我在 SQL 服务器上有这个查询,一个合并复制查询:
SELECT DISTINCT
b.tablenick,
b.rowguid,
c.generation,
sys.fn_MSgeneration_downloadonly
(
c.generation,
c.tablenick
)
FROM #belong b
LEFT OUTER JOIN dbo.MSmerge_contents c ON
c.tablenick = b.tablenick
AND c.rowguid = b.rowguid;
估计的查询计划包括有关 3 个查询的信息:
- 上面的查询
- 对 fn_MSgeneration_downloadonly 的函数调用
- 对 fn_MSArticle_has_downloadonly_property 的函数调用
实际的查询计划仅包含以下信息:
- 上面的查询
没有什么关于功能的。为什么实际计划中缺少功能信息?
我尝试了这些选项:
SET STATISTICS PROFILE ON
SET STATISTICS XML ON
它创建了一个实际计划,但它缺少与我在 Management Studio 中使用实际查询计划选项时相同的第 2 部分和第 3 部分。
例如,如果我要使用 Profiler 来捕获有关函数调用的信息,我会选择哪些事件?
没有找到与查询计划特别相关的答案,但我分析了 SP:StmtStarting 和 SP:StmtCompleted 并显示了函数调用。
出于性能原因,这是设计使然。
包含
BEGIN
和END
在定义中的函数为每个输入行创建一个新的 T-SQL 堆栈框架。换句话说,函数体为每个输入 row 单独执行。这一事实解释了与 T-SQL 标量和多语句函数相关的大多数性能问题(请注意,内联表值函数不使用该BEGIN...END
语法)。在您的问题的上下文中,这将导致
SHOWPLAN
每一行的完整输出。XML 计划输出非常冗长且生成成本很高,因此为每一行生成完整输出一般来说是个坏主意。例子
考虑下面的 T-SQL 标量函数,它是在AdventureWorks示例数据库中创建的,它返回给定 ID 的产品名称:
执行前计划
预执行计划(SSMS 中的估计计划)显示父语句和嵌套函数调用的计划信息:
SSMS 输出:
在SQL Sentry Plan Explorer中查看的相同 XML更清楚地显示了调用的嵌套性质:
执行后输出
当请求执行后计划输出时,SSMS 仅显示主查询的详细信息:
可以使用 SQL Server Profiler 中的Showplan XML Statistics Profile Event Class显示不这样做的性能影响,使用多次调用该函数的查询(每个输入行一次):
探查器输出:
函数执行有五个单独的执行后计划,父查询有一个。五个功能计划在分析器下部窗格中如下所示:
父查询计划是:
执行不带该
TOP (5)
子句的查询会为 Product 表中的 504 行中的每一行生成一个完整的执行计划。您可能会看到这将如何在更大的表中迅速失控。触发器的情况正好相反。这些不显示任何执行前计划信息,但包含执行后计划。这反映了触发器的基于集合的性质;每个受影响的行都会触发一次,而不是每行一次。