ユーザーストアドプロシージャの名前をsp_で開始するのはまだ間違っていますか?


33

私の同僚の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:CacheMissSelect1ストアドプロシージャよりも1つ多くのイベントを生成します(この記事では、SQL Server 7.0SQL Server 2000を参照しています)。

SQL Server 2008 R2環境で例を実行すると、SP:CacheMiss両方の手順(tempdbと別のテストデータベースの両方)で同じ量のイベントが発生します。

だから私は疑問に思っています:

  • 例の実行で何か間違ったことをしたことはありますか?
  • 'ユーザーに名前を付けないsproc sp_something' adagiumは、SQL Serverの新しいバージョンでもまだ有効ですか?
  • その場合、SQL Server 2008 R2での有効性を示す良い例はありますか?

これについてのあなたの考えをどうもありがとう!

編集

2番目の質問に答えるSQL Server 2008 R2のmsdnでストアドプロシージャ(データベースエンジン)の作成を見つけました。

プレフィックスとしてsp_を使用するストアドプロシージャを作成しないことをお勧めします。SQL Serverはsp_プレフィックスを使用して、システムストアドプロシージャを指定します。選択した名前は、将来のシステム手順と競合する可能性があります。[...]

ただし、プレフィックスを使用したことによるパフォーマンスの問題については何も言及されていませんsp_。SQL Server 2000以降に問題が解決したのか、それとも修正されたのかを知りたい。


3
以前にこれを見て、わずかなパフォーマンスの違いを発見しましたが、sp_バージョンを解決するオーバーヘッドをわずかに大きくしました(マスターデータベースとユーザーデータベースの両方でチェックする必要がありますmaster- システムのプロシージャを優先するため->ユーザーDBのプロシージャ->非システムprocs in master
マーティンスミス

4
ストアドプロシージャのプレフィックスを付けることでどのような利点がありますsp_か?これは、テーブルにプレフィックスを付けるのと同じくらい便利ですtbl。この意味のない命名規則を使用できるようにするために、システム検索マスターを最初に(パフォーマンスにわずかな違いがある場合でもパフォーマンスの違いがない場合でも)最初にするのはなぜですか?
アーロンバートランド

1
@AaronBertrand:正直に言うと、私は何の利益見えないすべてのを SP_、唯一の欠点でストアドプロシージャを接頭辞で、私はこの方法を自分でそれらを前に付けることはありません。しかし、同僚にもそれをしないように説得することができるすべての議論が欲しい。

1
ええ、tblは役に立たないが、私はまだそれを使用して大好きです。私のOCDを起動する必要があります。今すぐ私の芝生を下車します。
SQLRockstar

1
また、@ Josienには、同僚が命名スキームをより複雑にするための議論を用意する必要があります。なぜdbo.sp_Author_Renameがより良いかを説明してもらいますdbo.Author_Rename。理にかなった単一のことを考えることはできません。
アーロンバートランド

回答:


31

これは簡単にテストできます。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_プレフィックスの使用は遅い
  • スキーマプレフィックスの省略が遅い

もっと重要な質問:なぜあなたがなりたい SP_接頭辞を使用しますか?あなたの同僚はそうすることで何を得ると期待していますか?これは、これがより悪いことを証明しなければならないということではなく、システム内のすべてのストアドプロシージャに同じ3文字のプレフィックスを追加することを正当化することについてでなければなりません。メリットが見当たりません。

また、次のブログ投稿でこのパターンのかなり広範なテストを実行しました。

http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix


これらの結果はSQL Server 2012のものであることに注意してください。ただし、環境内で同じテストを実行できます。
アーロンバートランド

1
「あなたの共同作品はそうすることから何を得ると期待していますか」もハンガリー語表記を参照してください。基本的に、それはほとんどの場合90年代のものです。また、私の過去の仕事では、標準はすべてのストアドプロシージャに接頭辞を付けてsp_、他のものと区別できるようにし、名前の競合がないようにしました。このパフォーマンスの問題が存在するとは思いもしませんでした。
アールズ

素晴らしい例、アーロンに感謝します。私はまだ2008 R2でそれをテストしています(おそらく間違った方法でテストしているため、「dbo.wrapper_sp1」と「dbo.wrapper_sp2」は現在他の2つよりもかなり速いようです)。

12

プレフィックスとしてsp_を使用するストアドプロシージャを作成しないことをお勧めします。SQL Serverはsp_プレフィックスを使用して、システムストアドプロシージャを指定します。選択した名前は、将来のシステム手順と競合する可能性があります。[...]

ただし、sp_プレフィックスを使用したことによるパフォーマンスの問題については何も言及されていません。SQL Server 2000以降に問題が解決したのか、それとも修正されたのかを知りたい。

Martin Smithの簡単なコメントが示すように-はい、sp_プレフィックス付きのストアドプロシージャがある場合-SQL Serverクエリエグゼキュータは常にmasterデータベースをチェックインして、その名前のストアドプロシージャ(システムストアドプロシージャとしてマークされている)が存在するかどうかを確認します。

そして、存在する場合、masterデータベースからのそのシステムストアドプロシージャが常に優先され、独自のプロシージャの代わりに実行されます。

そうです-それはまだ立って:使用していないsp_接頭辞を。


5
テストが簡単。CREATE PROC dbo.sp_helptext AS SELECT 1試してくださいEXEC dbo.sp_helptext
マーティンスミス

あなたの答えをありがとう、masterspの有病率に非常に有用な追加。

2

より良いテストは、完全な最適化を必要とするクエリを書くことです。なぜなら、それはおそらくあなたが書いているprocが何をしているかをよりよく反映しているからです。次のクエリを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

両方のケースで同じ数のキャッシュミスおよびヒットイベントが発生し、両方のケースでプランがキャッシュに追加されました。また、両方のprocを数回実行しましたが、dm_exec_query_statsによって報告されるCPU時間または経過時間に一貫した差はありませんでした。

もう1つの懸念は、「sp_」プロシージャをマスターから実行できるため、作業中のDBの代わりにマスターで実行されたプロシージャのコピーを取得できることですが、クイックテストではそうではないことが示されます。ただし、作業中のDBからprocが削除され、masterにコピーが存在する場合、古いバージョンの場合は問題になる可能性があります。これが心配な場合は、「sp_」を使用してprocに名前を付けません。


興味深い発見、ありがとう!あなたの例をアーロンの例と組み合わせて使用​​して、さらにテストを実行します。

1

この問題は、完全修飾オブジェクト名を指定しない場合に関係があると考えています。したがって、「EXEC sp_something」は最初にマスターをチェックしますが、「EXEC dbname.dbo.sp_something」は最初にマスターに移動しません。

私が思い出すなら、レッスンは常に完全修飾名を使用することです。


5
それが違いを生むとは思わないでください。ユーザーデータベースにある場合でも、EXEC MyDB.dbo.sp_helptext 'sp_helptext'からのmaster1つを使用します。私の知る限り、両方の場所をチェックし、master存在する場合はそれを使用し、システムオブジェクトとしてマークされます。
マーティンスミス

1
2012年の@MartinSmith は、ローカルコピーを削除しない限り(マスターバージョンを実行した場合)、実行するマスターバージョンを強制することはできませんでした(そこにあるテストは何かが起こっていることを示しましたがMyDB.dbo.sp_foo)。この動作がどこで変更されたかを確認するための2008/2008 R2は今のところありません。
アーロンバートランド

@AaronBertrand-ああ、2008 R2でテストを行ったのは興味深い。
マーティンスミス

また、ローカルプロシージャが見つからず、マスターで見つかった場合、後者が実行され、これが発生するためにシステムオブジェクトとしてマークする必要がないことに注意してください。そして少なくとも2012年には、マスターコピーがシステムオブジェクトとしてマークされているかどうかにかかわらず、動作を変更しません。ローカルdb /スキーマプレフィックスの有無にかかわらず、ローカルコピーは存在しない限り常に実行されます。
アーロンバートランド

1
おっと、コメントが提案された回答に向けられていることを明確にすべきでした。SQLRockstarのコメント「EXEC dbname.dbo.sp_somethingは最初にマスターに移動しません。」間違っています。
グリーンストーンウォーカー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.