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)
表扫描属性...
T-SQL 与调用该函数的代码分开管理非内联表值函数的执行计划。它将其视为黑匣子,这就是为什么您在查询计划中看到 UDF 而不是 UDF\xe2\x80\x99s 内容。这可能与以下事实有关:非内联表值函数可以有多个语句,而查询计划只能显示单个语句(?)(或者至少看起来是这样)。
\n\n米凯尔·埃里克森评论道:
\n\n\n\n\n您有一个多语句表值函数,SQL Server 无法查看该函数并显示该函数的执行计划。您在此处看到的扫描是对函数返回的行的扫描,并且由于没有 where 子句,因此扫描是最好的选择。
\n
...并链接到此pastebin,显示如何查看非内联表值函数的缓存查询计划。
\n\n如果您的函数至少执行过一次(例如,SELECT * FROM myUdf()
),那么它应该缓存在 SQL Server 中。要显示缓存的计划,请使用函数名称减去任何模式并将其插入下面的查询中(引用自 Mikael 的代码):
\n\n\nRun Code Online (Sandbox Code Playgroud)\nselect\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
在结果集中,该QueryText
列应显示函数中的语句,并且QueryPlan
应包含 XML 查询计划。在 SSMS 中,如果单击某个QueryPlan
单元格,它将自动打开一个新的查询计划查看器窗口。您将需要查看函数的源代码并将其与语句交叉引用,然后单击查询计划来搜索性能问题。