存储过程与函数编译和性能差异

时间:2013-12-10 13:31:55

标签: sql-server stored-procedures

最近我给出了一个非常简单的访问者,让我解释了存储过程和UDF之间最基本的区别。

我能够回忆起一些差异listed here,但他不接受任何差异作为 BASIC 的差异。

根据他的回答是SP只编译一次,而每次调用UDF时都会编译,导致UDF比存储过程慢得多。

现在我已经搜索了但是无法明确判断这个断言是否属实。 请验证这一点。

3 个答案:

答案 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的函数。换句话说,现有的执行计划被重用。与存储过程相同的行为。