同僚の1人が、SQL Server 2008 R2データベースのストアドプロシージャにsp_something
という名前を付けました。これを見たとき、すぐに「それは間違っている!」と思いました。そして、ブックマークの検索を開始しました このオンライン記事 これが間違っている理由を説明しているので、同僚に説明を提供できます。
( Brian Moran による)記事では、ストアドプロシージャにsp _プレフィックスを付けると、SQL Serverがコンパイルされたプランのマスターデータベースを参照するようになると説明されています。 sp_sproc
がそこにないため、SQL Serverはプロシージャを再コンパイルします(そのために排他的なコンパイルロックが必要で、パフォーマンスの問題が発生します)。
次の例は、2つの手順の違いを示すために記事に記載されています。
USE tempdb;
GO
CREATE PROCEDURE dbo.Select1 AS SELECT 1;
GO
CREATE PROCEDURE dbo.sp_Select1 AS SELECT 1;
GO
EXEC dbo.sp_Select1;
GO
EXEC dbo.Select1;
GO
これを実行してから、プロファイラーを開き(ストアドプロシージャ-> SP:CacheMiss
イベントを追加)、ストアドプロシージャを再度実行します。 2つのストアドプロシージャの違いがわかるはずです。sp_Select1
ストアドプロシージャは、SP:CacheMiss
ストアドプロシージャよりも1つ多いSelect1
イベントを生成します(この記事ではSQL Server 7.およびSQL Server 20。)
SQL Server 2008 R2環境でこの例を実行すると、両方の手順(tempdbと別のテストデータベースの両方)で同じ量のSP:CacheMiss
イベントが発生します。
だから私は思っています:
sproc sp_something
'アダジウムは有効ですか?これについてあなたの考えをありがとう!
[〜#〜]編集[〜#〜]
SQL Server 2008 R2のmsdnに ストアドプロシージャ(データベースエンジン)の作成 が見つかりました。これが2番目の質問の答えです。
Sp_を接頭辞として使用してストアドプロシージャを作成しないことをお勧めします。 SQL Serverは、sp_プレフィックスを使用してシステムストアドプロシージャを指定します。選択した名前は、将来のシステム手順と競合する可能性があります。 [...]
ただし、sp_
接頭辞を使用したことが原因で発生するパフォーマンスの問題については何も言及されていません。それでも問題ないのか、それともSQL Server 2000以降に修正されたのか知りたいです。
これは自分でテストするのがかなり簡単です。 2つの非常に単純な手順を作成してみましょう。
CREATE PROCEDURE dbo.sp_mystuff
AS
SELECT 'x';
GO
CREATE PROCEDURE dbo.mystuff
AS
SELECT 'x';
GO
次に、スキーマプレフィックスの有無にかかわらず、それらを何度も実行するラッパーを作成します。
CREATE PROCEDURE dbo.wrapper_sp1
AS
BEGIN
SET NOCOUNT ON;
DECLARE @i INT = 1;
WHILE @i <= 1000
BEGIN
EXEC sp_mystuff;
SET @i += 1;
END
END
GO
CREATE PROCEDURE dbo.wrapper_1
AS
BEGIN
SET NOCOUNT ON;
DECLARE @i INT = 1;
WHILE @i <= 1000
BEGIN
EXEC mystuff;
SET @i += 1;
END
END
GO
CREATE PROCEDURE dbo.wrapper_sp2
AS
BEGIN
SET NOCOUNT ON;
DECLARE @i INT = 1;
WHILE @i <= 1000
BEGIN
EXEC dbo.sp_mystuff;
SET @i += 1;
END
END
GO
CREATE PROCEDURE dbo.wrapper_2
AS
BEGIN
SET NOCOUNT ON;
DECLARE @i INT = 1;
WHILE @i <= 1000
BEGIN
EXEC dbo.mystuff;
SET @i += 1;
END
END
GO
結果:
結論:
より重要な質問:なぜsp_接頭辞を使用したいのですか?あなたの同僚はそうすることから得る何を期待していますか?これは、これがさらに悪いことを証明する必要があるということではなく、システム内のすべてのストアドプロシージャに同じ3文字のプレフィックスを追加することを正当化することに関するものです。メリットがわかりません。
また、次のブログ投稿で、このパターンのかなり広範なテストを実行しました。
http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix
Sp_を接頭辞として使用してストアドプロシージャを作成しないことをお勧めします。 SQL Serverは、sp_プレフィックスを使用してシステムストアドプロシージャを指定します。選択した名前は、将来のシステム手順と競合する可能性があります。 [...]
ただし、sp_接頭辞の使用によって引き起こされるパフォーマンスの問題については何も言及されていません。それでも変わらないのか、SQL Server 2000以降に修正されたのか知りたい。
マーティン・スミスの簡単なコメントが示すように-はい、sp_
プレフィックス-SQL Serverクエリエグゼキューターはalwaysmaster
データベースを最初にチェックして、その名前のストアドプロシージャ(システムストアドプロシージャとしてマークされている)が存在するかどうかを確認します。
そして、存在する場合、master
データベースのそのシステムストアドプロシージャが常に優先され、独自のプロシージャの代わりに実行されます。
だからはい-それはまだ立っています:使用しないでください the sp_
接頭辞。
より適切なテストは、完全な最適化を必要とするクエリを記述することです。これは、記述しているプロシージャが何をしているかをよりよく反映しているためです。次のクエリをSPで囲み、テストを繰り返したところ、同じ結果が得られました。
select * from Person.BusinessEntity b
inner join Person.BusinessEntityAddress ba on b.BusinessEntityID = ba.BusinessEntityID
inner join Person.Address a on ba.AddressID = a.AddressID
どちらの場合も同じ数のキャッシュミスイベントとヒットイベントがあり、どちらの場合もプランがキャッシュに追加されました。また、両方のプロシージャを数回実行しましたが、dm_exec_query_statsによって報告されるCPU時間または経過時間に一貫した違いはありませんでした。
もう1つの懸念は、「sp_」プロシージャはマスターから実行できるため、作業中のDBではなくマスターで実行されたプロシージャのコピーを取得できることですが、簡単なテストではそうではありません。ただし、作業しているDBからprocが削除され、コピーがマスターに存在する場合、それが実行され、古いバージョンの場合は問題となる可能性があります。これが問題になる場合は、 "sp_"を使用してプロシージャに名前を付けません。
完全修飾オブジェクト名を指定しないと、問題が発生するはずです。したがって、「EXEC sp_something」は最初にマスターをチェックしますが、「EXEC dbname.dbo.sp_something」は最初にマスターに移動することはありません。
私が覚えているとしたら、レッスンは常に完全修飾名を使用することです。