SQL Serverの世界には、すべてのオブジェクトにプレフィックスを付けるのが好きな人とそうでない人の2種類があります。前者のグループはさらに2つのカテゴリに分類されます。ストアドプロシージャの前にsp_
を付けるグループです。 、および他のプレフィックス(usp_
など)を選択するユーザー またはproc_
)。長年の推奨事項は、sp_
を回避することでした。 パフォーマンス上の理由と、システムカタログにすでに存在する名前を選択した場合のあいまいさや衝突を避けるために、プレフィックスを付けます。衝突は確かにまだ問題ですが、オブジェクト名を精査したとすると、それでもパフォーマンスの問題ですか?
TL; DRバージョン:はい。
sp_プレフィックスはまだノーノーです。 ただし、この投稿では、SQL Server 2012で、この警告のアドバイスが適用されなくなったと思われる理由と、この命名規則を選択した場合のその他の潜在的な副作用について説明します。
sp_の問題は何ですか?
sp_
プレフィックスは、あなたが思っていることを意味するものではありません。ほとんどの人は、sp
と考えています。 実際には「特別」を意味する場合は、「ストアドプロシージャ」の略です。 sp_
を使用してマスターに格納されたストアドプロシージャ(およびテーブルとビュー) プレフィックスは、適切な参照なしで任意のデータベースからアクセスできます(ローカルバージョンが存在しない場合)。プロシージャがシステムオブジェクトとしてマークされている場合(sp_MS_marksystemobject
を使用) (is_ms_shipped
を設定する文書化されていないサポートされていないシステムプロシージャ 1)の場合、masterのプロシージャは、呼び出し元のデータベースのコンテキストで実行されます。簡単な例を見てみましょう:
CREATE DATABASE sp_test; GO USE sp_test; GO CREATE TABLE dbo.foo(id INT); GO USE master; GO CREATE PROCEDURE dbo.sp_checktable AS SELECT DB_NAME(), name FROM sys.tables WHERE name = N'foo'; GO USE sp_test; GO EXEC dbo.sp_checktable; -- runs but returns 0 results GO EXEC master..sp_MS_marksystemobject N'dbo.sp_checktable'; GO EXEC dbo.sp_checktable; -- runs and returns results GO
結果:
(0 row(s) affected) sp_test foo (1 row(s) affected)
パフォーマンスの問題は、プロシージャのローカルバージョンが存在するかどうか、およびマスターに同等のオブジェクトが実際に存在するかどうかに応じて、マスターが同等のストアドプロシージャをチェックする可能性があるという事実に起因します。これにより、追加のメタデータオーバーヘッドと、追加のSP:CacheMiss
が発生する可能性があります。 イベント。問題は、このオーバーヘッドが具体的かどうかです。
それでは、テストデータベースでの非常に簡単な手順を考えてみましょう。
CREATE DATABASE sp_prefix; GO USE sp_prefix; GO CREATE PROCEDURE dbo.sp_something AS BEGIN SELECT 'sp_prefix', DB_NAME(); END GO
そしてマスターでの同等の手順:
USE master; GO CREATE PROCEDURE dbo.sp_something AS BEGIN SELECT 'master', DB_NAME(); END GO EXEC sp_MS_marksystemobject N'sp_something';
CacheMiss:事実かフィクションか?
テストデータベースからクイックテストを実行すると、これらのストアドプロシージャを実行しても、プロシージャを適切にデータベースまたはスキーマで修飾するか(一般的な誤解)、またはマークを付けるかどうかに関係なく、マスターからバージョンが実際に呼び出されることはありません。システムオブジェクトとしてのマスターバージョン:
USE sp_prefix; GO EXEC sp_prefix.dbo.sp_something; GO EXEC dbo.sp_something; GO EXEC sp_something;
結果:
sp_prefix sp_prefix sp_prefix sp_prefix sp_prefix sp_prefix
クイックトレースSP:CacheMiss
があるかどうかを確認します イベント:
CacheMiss
が表示されます ストアドプロシージャを呼び出すアドホックバッチのイベント(SQL Serverは通常、主にプロシージャ呼び出しで構成されるバッチをキャッシュしないため)が、ストアドプロシージャ自体のイベントではありません。 sp_something
がある場合とない場合の両方 マスターに存在するプロシージャ(および存在する場合は、システムオブジェクトとしてマークされている場合とされていない場合の両方)、sp_something
の呼び出し ユーザーデータベースでは、マスターのプロシージャを「誤って」呼び出したり、CacheMiss
を生成したりすることはありません。 手順のイベント。
これはSQLServer2012で行われました。SQLServer2008R2で上記と同じテストを繰り返したところ、わずかに異なる結果が見つかりました。
したがって、SQL Server 2008 R2では、追加のCacheMiss
が表示されます。 SQL Server 2012では発生しないイベント。これはすべてのシナリオで発生します(同等のオブジェクトマスターがない、マスター内のオブジェクトがシステムオブジェクトとしてマークされている、マスター内のオブジェクトがシステムオブジェクトとしてマークされていない)。すぐに、この追加のイベントがパフォーマンスに顕著な影響を与えるかどうかに興味がありました。
パフォーマンスの問題:事実かフィクションか?
sp_
なしで追加の手順を実行しました 生のパフォーマンスを比較するためのプレフィックス、CacheMiss
さておき:
USE sp_prefix; GO CREATE PROCEDURE dbo.proc_something AS BEGIN SELECT 'sp_prefix', DB_NAME(); END GO
したがって、sp_something
の唯一の違いは およびproc_something
。次に、EXEC sp_prefix.dbo.<procname>
を使用して、ラッパープロシージャを作成し、それぞれ1000回実行しました。 、EXEC dbo.<procname>
およびEXEC <procname>
構文。同等のストアドプロシージャがマスターに存在し、システムオブジェクトとしてマークされ、マスターに存在するがシステムオブジェクトとしてマークされておらず、マスターにまったく存在しない。
USE sp_prefix; GO CREATE PROCEDURE dbo.wrap_sp_3part AS BEGIN DECLARE @i INT = 1; WHILE @i <= 1000 BEGIN EXEC sp_prefix.dbo.sp_something; SET @i += 1; END END GO CREATE PROCEDURE dbo.wrap_sp_2part AS BEGIN DECLARE @i INT = 1; WHILE @i <= 1000 BEGIN EXEC dbo.sp_something; SET @i += 1; END END GO CREATE PROCEDURE dbo.wrap_sp_1part AS BEGIN DECLARE @i INT = 1; WHILE @i <= 1000 BEGIN EXEC sp_something; SET @i += 1; END END GO -- repeat for proc_something
SQL Sentry Plan Explorerを使用して各ラッパープロシージャの実行時間を測定すると、結果はsp_
を使用していることを示しています。 プレフィックスは、ほとんどすべての場合(そして確かに平均して)の平均期間に大きな影響を与えます:
<!-target =_blank href ="http://www.sqldat.com/article/uploadfiles/202205/2022051415101638.png">
また、SQL Server 2012のパフォーマンスは、SQL Sevrer2008R2のパフォーマンスよりもはるかに優れていることがわかります。他の変数に違いはありません。両方のインスタンスは同じホスト上にあり、どちらもメモリやその他のあらゆる種類のプレッシャーにさらされていません。これは、追加のCacheMiss
の組み合わせである可能性があります イベントと、バージョン間でデータベースエンジンに加えられた機能強化から得られる透過的な改善。
別の副作用:あいまいさ
作成したオブジェクトを参照するストアドプロシージャを作成する場合は、dbo.sp_helptext
と言います。 、そしてこの名前がシステムプロシージャ名と衝突することに気づかなかった(または気にしなかった)場合、誰かがストアドプロシージャをレビューしているときに、あいまいさが生じる可能性があります。彼らはおそらく、あなたがたまたまその名前を共有するために作成した別のプロシージャではなく、システムプロシージャを意味していると想定します。
sp_
のプレフィックスが付いたストアドプロシージャを参照するストアドプロシージャを作成すると、もう1つの興味深いことが起こります。 それはたまたまマスターにも存在します。すぐにはなじみがない可能性がある(したがって、私が説明しているシナリオを代表する可能性が高い)既存の手順を選択してみましょう:sp_resyncuniquetable
。
CREATE PROCEDURE dbo.test1 AS BEGIN EXEC dbo.sp_resyncuniquetable; END GO
Management Studioでは、マスターにその名前の有効なプロシージャがあるため、IntelliSenseはストアドプロシージャ名に無効なアンダースコアを付けません。したがって、下に波線が表示されていなくても、プロシージャはすでに存在していると見なすことができます(また、masterのプロシージャをエラーなしで実行できると仮定すると、QA /テストにも合格する可能性があります)。再同期プロシージャに別の名前を選択した場合は、proc_resyncuniquetable
としましょう。 、このあいまいさの可能性はまったくありません(誰かがマスターでそのプロシージャを手動で作成しない限り、これは発生する可能性があります)。プロシージャがまだ存在しない場合でも、呼び出し元は正常に作成されますが(名前解決が延期されているため)、次の警告が表示されます:
The module 'test1' depends on the missing object 'dbo.proc_resyncuniquetable'. The module will still be created; however, it cannot run successfully until the object exists.
このシナリオでは、もう1つのあいまいさの原因が発生する可能性があります。次の一連のイベントは完全にもっともらしいです:
- プロシージャの初期バージョン、たとえば
sp_foo
を作成します 。 - デプロイヤが誤ってマスターにバージョンを作成します(おそらく気付くか、気付かないかもしれませんが、どちらの場合もクリーンアップされません)。
- デプロイヤー(または他の誰か)が、今回は適切なデータベースにプロシージャを作成します。
- 時間の経過とともに、
your_database.dbo.sp_foo
に複数の変更を加えます。 。 -
sp_foo
を置き換えますsp_superfoo
を使用 、sp_foo
を削除します ユーザーデータベースから。 - 新しいストアドプロシージャを参照するようにアプリケーションを更新する場合、さまざまな理由で1つか2つの置換を見逃す可能性があります。
したがって、このシナリオでは、アプリケーションは引き続きsp_foo
を呼び出しています。 、そして、ローカルコピーを削除したとしても、マスターで同等であると見なすものが見つかるため、失敗することはありません。マスターのこのストアドプロシージャは、sp_superfoo
と同等ではないだけではありません。 、最新バージョンのsp_foo
と同等ではありません 。
「手順が見つかりません」は、「手順が存在しませんが、それを呼び出すコードは機能し、期待される結果を完全に返さない」よりもトラブルシューティングがはるかに簡単な問題です。
結論
SQL Server 2012で動作が少し変更されたとしても、sp_
を使用するべきではないと私はまだ考えています。 マスターでストアドプロシージャを作成し、それをシステムオブジェクトとしてマークすることを意図していない限り、いつでもプレフィックスを付けることができます。そうしないと、これらのパフォーマンスの問題と、複数の面での潜在的なあいまいさにさらされます。
個人的には、ストアドプロシージャにプレフィックスを付ける必要はまったくないと思いますが、他にどのような種類のオブジェクトが可能かを尋ねる以外に、それを納得させる具体的な証拠はありません。ビュー、関数、またはテーブルを実行することはできません…
私がよく提案するように、あなたが一貫している限り、私はあなたの命名規則が何であるかを本当に気にしません。ただし、sp_
のような潜在的に有害なプレフィックスは避けるべきだと思います。 。