2013-12-10 8 views
6

最近、私はインタビュー担当者がストアドプロシージャとUDFの最も基本的な違いを説明するように求めているinetrviewを出しました。ストアドプロシージャと関数のコンパイルとパフォーマンスの違い

listed hereのように2つの違いを思い出すことができましたが、彼はBASICという違いを受け入れませんでした。

答えたのは、SPは一度しかコンパイルされていないが、UDFが呼び出されるたびにコンパイルされるため、UDFがストアドプロシージャよりもかなり遅くなるということだ。

今、私は検索しましたが、このアサーションが真であるかどうかを明確に判断できませんでした。 これを確認してください。

+0

私はUDFの推定行数が常に1であることを知っています... –

+0

彼らは間違っています。 UDFは呼び出されるたびに再コンパイルされません。これは多くの方法を証明することが可能です。例えばプロファイラでイベントをトレース(再)し、DMVをキャッシュするプランを見てください。 [私の答えはこちら](http://stackoverflow.com/questions/19884138/why-sql-functions-are-faster-than-udf/19891697#19891697)は、UDFを複数回実行するとスタックトレースを調べます。オーバーヘッドはコンパイルではなく実行中です。 –

+0

どのような種類の関数 - スカラーまたはインラインのテーブル値またはマルチステートメントのテーブル値ですか?3つは、実行メカニズムの異なるオブジェクトの種類です(インラインTVFはインライン展開されています:-)。 –

答えて

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%' 

をあなたはこのクエリ自体のためのコンパイルされた計画である1つのレコードのみ、すなわちアドホックオブジェクト型が表示されます。

関数rre-executeを実行した後、このクエリを再度実行します。 ProcのObject-Typeを持つ関数のコンパイルされたプランを含む多くのレコードが表示されます。

これが役に立ちます。

+0

ありがとうmanaoj bhai ..私はあなたのブログをブックマークしました...そこから多くを学ぶでしょう。 –

+0

おかげさまで、私の読者としてあなたをお待ちしています。 –

4

これは奇妙なことですが、UDFとSPは同じようにコンパイルされています(変更されたときに再コンパイルされます)。インタビュアーで混在したUDFと動的(非パラメトリック)クエリーが混在しているように見えます。誰かがその議論を維持するために少しの情報を見つけた場合は、それを報告してください。

+0

これを追加するには、Scalar UDFが遅くなる可能性があります。この記事とそれに続く議論は素晴らしい講演です。 http://www.sqlservercentral.com/articles/T-SQL/91724/ – jean

3

ジーンは間違いなく一度だけコンパイルされます。

次のクエリは、読み込み、あなたのプロシージャキャッシュを与えると、そのような実行回数として有用なメトリックが含まれますなど:

私は実行に機能はでは1よりも高いカウント見ることができる午前レポートで
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 

つまり、既存の実行計画が再利用されます。ストアドプロシージャと同じ動作です。

関連する問題