web-dev-qa-db-ja.com

EXECとSP_EXECUTESQLのパフォーマンス

最近、データベースに対してSQLコードレビューツールを使用しました。 EXECの代わりにSP_EXECUTESQLを使用することをお勧めします。

SP_EXECUTESQLは、SQLインジェクションを回避するのに役立ちます。 EXECSP_EXECUTESQLを使用する場合、パフォーマンスに違いはありますか?.

7

これは、セキュリティと一貫性のために主に優先されるものであり、パフォーマンスとは何の関係もありません(ただし、SQL Serverの古いバージョンではそれが問題であった可能性があります)。

パラメータがあるときに常に_sp_executesql_を使用する必要があるときにEXEC()を使用する理由EXEC()は、すべての変数を単一の文字列に連結するように強制します。これにより、乱用に熟します。

これについては、ここで詳しく説明しました。

ここでは、SQLインジェクションから身を守る方法についても書きました。

SQLインジェクションはかなり大きな問題であり、他の多くの人々もそれについて書いています。

最後に、システムプロシージャを呼び出すときは、_sys.all_objects_に格納されているものと一致する適切な大文字小文字を使用していることを確認してください。すべて小文字にする必要があります。そうしないと、コードが大文字と小文字を区別するインスタンスにデプロイされると、すべて失敗し始めます。

5
Aaron Bertrand

まず、両方のコマンドの意味を確認してみましょう。
_sp_executesql_:何度も再利用できるTransact-SQLステートメントまたはバッチ、または動的に構築されたものを実行します。 Transact-SQLステートメントまたはバッチには、埋め込みパラメーターを含めることができます。
exec:Transact-SQLバッチ内のコマンド文字列または文字列、またはシステムストアドプロシージャ、ユーザー定義のストアドプロシージャ、CLR(共通言語ランタイム)のいずれかを実行しますプロシージャ、スカラー値のユーザー定義関数、または拡張ストアドプロシージャ。 EXECUTEステートメントを使用して、パススルーコマンドをリンクサーバーに送信できます。

主な違いのいくつか:

  1. _sp_executesql_では、ステートメントをパラメータ化できるため、SQLインジェクションの点でEXECよりも安全です。
  2. _sp_executesql_は、キャッシュされたクエリプランを活用できます。TSQL文字列は1回だけ作成され、その後、同じクエリが_sp_executesql_で呼び出されるたびに、SQL Serverはキャッシュからクエリプランを取得して再利用します。
  3. EXECで作成された一時テーブルは、一時テーブルキャッシュメカニズムを使用できません。

参照:
https://blogs.msdn.Microsoft.com/turgays/2013/09/17/exec-vs-sp_executesql/
https://msdn.Microsoft.com/en-us/library/ms188001.aspx
https://msdn.Microsoft.com/en-us/library/ms188332.aspx

編集:
パフォーマンスに関する次の記事を見つけました:
パフォーマンスは、ストアドプロシージャのこれら2つの方法の間の議論の問題です。その名前が示すように、_sp_execute_自体は、システムデータベースに格納されるストアドプロシージャです。したがって、_SP_ExecuteSQL_にはSQL文字列を渡す必要があります。ただし、キャッシュの可能性が高い場合を除き、2回目以降の実行ではパフォーマンスが向上します。

つまり、パラメータ化された動的T-SQLは再利用を促進します。さらに、sp_executeは、exec()に対して動的クエリを実行しているときに不要なコンパイルを回避する可能性が高いと考えられます。しかし、一部の専門家は、両方の方法について計画がキャッシュされると考えるので、それを誤解を招くものと見なします。実際、_SP_ExecuteSQL_のパラメーター化されていないクエリの場合、後者と同じ特性が示されます。

http://www.technovisitors.com/2014/07/SPExecuteSQL-Vs-Execute-SQL-Server.html

3
Ahmad Abuhasna

EXECはアドホックキャッシュを使用し、アドホックプランの肥大化を引き起こす可能性がありますが、sp_executesqlはそうしませんが、プランの安定度に依存します。

0
Darren