表值函数非常慢

K09*_*K09 5 sql-server index-tuning

我有一个 TVF,调用时需要 10 秒才能运行。

但是,如果我在该 TVF 内进行查询,则只需要 1 秒。我已在此基础查询表上添加了正确的索引。

在 TVF 的执行计划中,它正在执行表扫描。我如何找出它这样做的原因?

谢谢。

询问...

select Username, Identifier 
from [dbo].Unmapped(@CustID, @StartDate, @EndDate)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

表扫描属性...

在此输入图像描述

bin*_*nki 2

T-SQL 与调用该函数的代码分开管理非内联表值函数的执行计划。它将其视为黑匣子,这就是为什么您在查询计划中看到 UDF 而不是 UDF\xe2\x80\x99s 内容。这可能与以下事实有关:非内联表值函数可以有多个语句,而查询计划只能显示单个语句(?)(或者至少看起来是这样)。

\n\n

米凯尔·埃里克森评论道:

\n\n
\n

您有一个多语句表值函数,SQL Server 无法查看该函数并显示该函数的执行计划。您在此处看到的扫描是对函数返回的行的扫描,并且由于没有 where 子句,因此扫描是最好的选择。

\n
\n\n

...并链接到此pastebin,显示如何查看非内联表值函数的缓存查询计划

\n\n

如果您的函数至少执行过一次(例如,SELECT * FROM myUdf()),那么它应该缓存在 SQL Server 中。要显示缓存的计划,请使用函数名称减去任何模式并将其插入下面的查询中(引用自 Mikael 的代码):

\n\n
\n
select\n  PlanCreated       = qs.creation_time,\n  ObjectName        = object_name(st.objectid),\n  QueryPlan         = cast(qp.query_plan as xml),\n  QueryText         = substring(st.text, 1 + (qs.statement_start_offset / 2), 1 + ((isnull(nullif(qs.statement_end_offset, -1), datalength(st.text)) - qs.statement_start_offset) / 2))\nfrom sys.dm_exec_query_stats as qs\n  cross apply sys.dm_exec_sql_text(qs.sql_handle) as st\n  cross apply sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) as qp\nwhere object_name(st.objectid) = \'FunctionName\'\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

在结果集中,该QueryText列应显示函数中的语句,并且QueryPlan应包含 XML 查询计划。在 SSMS 中,如果单击某个QueryPlan单元格,它将自动打开一个新的查询计划查看器窗口。您将需要查看函数的源代码并将其与语句交叉引用,然后单击查询计划来搜索性能问题。

\n