web-dev-qa-db-ja.com

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

同僚の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イベントが発生します。

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

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

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

[〜#〜]編集[〜#〜]

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

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

ただし、sp_接頭辞を使用したことが原因で発生するパフォーマンスの問題については何も言及されていません。それでも問題ないのか、それともSQL Server 2000以降に修正されたのか知りたいです。

33
user5147

これは自分でテストするのがかなり簡単です。 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

結果:

enter image description here

結論:

  • sp_接頭辞の使用は遅い
  • スキーマプレフィックスを省略すると遅くなる

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

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

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

32
Aaron Bertrand

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

ただし、sp_接頭辞の使用によって引き起こされるパフォーマンスの問題については何も言及されていません。それでも変わらないのか、SQL Server 2000以降に修正されたのか知りたい。

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

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

だからはい-それはまだ立っています:使用しないでください the sp_接頭辞。

12
marc_s

より適切なテストは、完全な最適化を必要とするクエリを記述することです。これは、記述しているプロシージャが何をしているかをよりよく反映しているためです。次のクエリを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_"を使用してプロシージャに名前を付けません。

2
cfradenburg

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

私が覚えているとしたら、レッスンは常に完全修飾名を使用することです。

1
SQLRockstar