最近我给出了一个非常简单的访问者,让我解释了存储过程和UDF之间最基本的区别。
我能够回忆起一些差异listed here,但他不接受任何差异作为 BASIC 的差异。
根据他的回答是SP只编译一次,而每次调用UDF时都会编译,导致UDF比存储过程慢得多。
现在我已经搜索了但是无法明确判断这个断言是否属实。 请验证这一点。
答案 0 :(得分:5)
@mhasan,谢谢你在我的问题中提到我的博客文章。
据我所知,存储过程& 功能在编译和编辑方面都有相同的行为。重新编译。两者都未预编译。当您创建其中任何一个时,它们只是被解析和创建,但不会被编译。两者都是在第一次执行时编译的。如果对它们进行任何更改,它们可以再次自动重新编译。
创建新函数后执行以下查询:
SELECT objtype, cacheobjtype, usecounts, text
FROM sys.dm_exec_cached_plans AS p
CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t
WHERE t.text LIKE '%YourNewFunctionName%'
您将只看到一条记录,即此查询本身的编译计划,即Adhoc对象类型。
执行函数后,再次执行此查询。您将看到更多记录,包括函数的编译计划,其中包含一个Object-Type of Proc。
希望这有帮助。
答案 1 :(得分:4)
这是一个奇怪的陈述,到目前为止我知道UDF和SP被编译(并且在它改变时重新编译)等。面试者看起来混合UDF与动态(非参数)查询。如果有人发现轻微信息以支持该论点,请报告。
答案 2 :(得分:3)
Jean是正确的,他们肯定会编译一次。
以下查询将为您提供过程缓存并包含有用的指标,如执行计数,读取等:
SELECT TOP 1000 DB_NAME(qt.dbid) AS DB,
OBJECT_NAME(qt.objectid, qt.dbid) AS 'object_name',
qs.total_worker_time,
qs.execution_count,
qs.total_logical_reads,
plan_generation_num,
SUBSTRING(qt.text, ( qs.statement_start_offset / 2 ) + 1,
( ( CASE statement_end_offset
WHEN -1 THEN DATALENGTH(qt.text)
ELSE qs.statement_end_offset
END - qs.statement_start_offset ) / 2 ) + 1) AS 'query'
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
LEFT JOIN sys.objects o
ON o.object_id = qt.objectid
WHERE qs.execution_count > 0
AND DATEDIFF(Second, qs.creation_time, GETDATE()) > 0
AND DATEDIFF(Minute, qs.creation_time, GETDATE()) > 0
ORDER BY /*Sort functions first*/
CASE
WHEN o.type_desc LIKE '%FUNCTION' THEN 0
ELSE 1
END,
qs.execution_count DESC
在报告中,我能够看到执行计数大于1的函数。换句话说,现有的执行计划被重用。与存储过程相同的行为。