Immer noch falsch, den Namen einer gespeicherten Benutzerprozedur mit sp_ zu starten?

33

Einer meiner Mitarbeiter hat eine gespeicherte Prozedur in unserer SQL Server 2008 R2-Datenbank benannt sp_something. Als ich das sah, dachte ich sofort: "Das ist FALSCH!" und fing an, in meinen Lesezeichen nach diesem Online-Artikel zu suchen , der erklärt, warum er falsch ist, damit ich meinem Kollegen eine Erklärung geben konnte.

In dem Artikel (von Brian Moran ) wird erläutert, dass SQL Server die Master-Datenbank nach einem kompilierten Plan durchsucht , wenn der gespeicherten Prozedur ein sp_- Präfix zugewiesen wird. Da sich der sp_sprocnicht dort befindet, kompiliert SQL Server die Prozedur neu (und benötigt dafür eine exklusive Kompilierungssperre, die zu Leistungsproblemen führt).

Das folgende Beispiel wird in dem Artikel angegeben, um den Unterschied zwischen zwei Prozeduren zu zeigen:

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

Sie führen dies aus, öffnen dann den Profiler (fügen Sie das SP:CacheMissEreignis Gespeicherte Prozeduren -> hinzu ) und führen die gespeicherten Prozeduren erneut aus. Sie sollten einen Unterschied zwischen den beiden gespeicherten Prozeduren feststellen: Die sp_Select1gespeicherte Prozedur generiert ein SP:CacheMissEreignis mehr als die Select1gespeicherte Prozedur (der Artikel verweist auf SQL Server 7.0 und SQL Server 2000 ).

Wenn ich das Beispiel in meiner SQL Server 2008 R2-Umgebung ausführe, erhalte ich SP:CacheMissfür beide Prozeduren die gleiche Anzahl von Ereignissen (sowohl in tempdb als auch in einer anderen Testdatenbank).

Ich frage mich also:

  • Kann ich bei der Ausführung des Beispiels etwas falsch gemacht haben?
  • Ist das sproc sp_somethingAdagium " Benutzer nicht benennen " in neueren Versionen von SQL Server noch gültig?
  • Wenn ja, gibt es ein gutes Beispiel für die Gültigkeit in SQL Server 2008 R2?

Vielen Dank für Ihre Gedanken dazu!

BEARBEITEN

Ich fand Stored Procedures (Database Engine) Erstellen von auf Msdn für SQL Server 2008 R2, die meine zweite Frage beantwortet:

Es wird empfohlen, keine gespeicherten Prozeduren mit sp_ als Präfix zu erstellen. SQL Server verwendet das Präfix sp_, um gespeicherte Systemprozeduren anzugeben. Der von Ihnen gewählte Name kann zu Konflikten mit zukünftigen Systemprozeduren führen. [...]

Über Leistungsprobleme, die durch die Verwendung des sp_Präfixes verursacht werden, wird dort jedoch nichts erwähnt . Ich würde gerne wissen, ob dies immer noch der Fall ist oder ob es nach SQL Server 2000 behoben wurde.

marc_s
quelle
3
Ich habe mir das schon einmal angesehen und dabei einen vernachlässigbaren Leistungsunterschied festgestellt, der auf einen geringfügig höheren Aufwand beim Auflösen der sp_Versionen zurückzuführen ist (muss sowohl in der Master- als auch in der Benutzerdatenbank eingecheckt werden, da System-Procs in master-> Procs in der Benutzer-DB -> non system Vorrang haben) procs in master)
Martin Smith
4
Welchen Nutzen sehen Sie für das Präfixieren einer gespeicherten Prozedur mit sp_? Dies ist ungefähr so ​​nützlich wie das Präfixieren einer Tabelle mit tbl. Warum sollte der Systemsuchmaster zuerst eingerichtet werden (auch wenn es sich um einen vernachlässigbaren oder keinen Leistungsunterschied handelt), damit Sie diese bedeutungslose Namenskonvention verwenden können?
Aaron Bertrand
1
@AaronBertrand: Um ehrlich zu sein, sehe ich keinen Nutzen überhaupt in sprocs mit sp_, nur Nachteile prefixing, und ich würde sie nie auf diese Weise selbst voranstellen . Aber ich möchte alle Argumente, die ich bekommen kann, um meine Mitarbeiter davon zu überzeugen, es auch nicht zu tun.
1
Ja, tbl ist nutzlos, aber ich liebe es immer noch, es zu benutzen. Muss meine Zwangsstörung sein. Jetzt geh von meinem Rasen.
SQLRockstar
1
@Josien auch, Ihre Mitarbeiter sollten mit Argumenten kommen, um ein Benennungsschema komplizierter zu machen. Lassen Sie sie erklären, warum dbo.sp_Author_Renamedas besser ist als dbo.Author_Rename. Mir fällt nichts ein, was Sinn macht.
Aaron Bertrand

Antworten:

31

Dies ist ziemlich einfach, sich selbst zu testen. Lassen Sie uns zwei sehr einfache Prozeduren erstellen:

CREATE PROCEDURE dbo.sp_mystuff
AS
  SELECT 'x';
GO
CREATE PROCEDURE dbo.mystuff
AS
  SELECT 'x';
GO

Erstellen wir nun einen Wrapper, der sie mehrmals mit und ohne das Schema-Präfix ausführt:

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

Ergebnisse:

Bildbeschreibung hier eingeben

Schlussfolgerungen:

  • Die Verwendung des Präfix sp_ ist langsamer
  • Das Auslassen des Schema-Präfixes ist langsamer

Die wichtigere Frage: Warum würden Sie wollen den sp_ Präfix benutzen? Was Ihre Mitarbeiter erwarten zu gewinnen , so zu tun? Es sollte nicht darum gehen, dass Sie beweisen müssen, dass dies schlimmer ist, sondern darum, dass Sie jedem einzelnen gespeicherten Vorgang im System dasselbe Präfix aus drei Buchstaben hinzufügen. Ich sehe den Nutzen nicht.

Außerdem habe ich dieses Muster in folgendem Blog-Beitrag ausführlich getestet:

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

Aaron Bertrand
quelle
Beachten Sie, dass sich diese Ergebnisse auf SQL Server 2012 beziehen. Sie können jedoch dieselben Tests in Ihrer Umgebung durchführen.
Aaron Bertrand
1
"Was erwarten Ihre Mitarbeiter davon?" Siehe auch Ungarische Notation . Im Grunde ist es eine Sache der 90er Jahre zum größten Teil. Bei meiner früheren Arbeit bestand der Standard darin, jeder gespeicherten Prozedur ein Präfix zuzufügen, sp_damit sie von anderen Dingen unterschieden werden konnte und keine Namenskonflikte auftraten. Ich hatte keine Ahnung, dass dieses Leistungsproblem damit bestand.
Earlz
Tolles Beispiel, danke Aaron. Ich teste es immer noch auf 2008 R2 (und teste es wahrscheinlich auf die falsche Weise, da "dbo.wrapper_sp1" und "dbo.wrapper_sp2" derzeit deutlich schneller zu sein scheinen als die beiden anderen).
12

Es wird empfohlen, keine gespeicherten Prozeduren mit sp_ als Präfix zu erstellen. SQL Server verwendet das Präfix sp_, um gespeicherte Systemprozeduren anzugeben. Der von Ihnen gewählte Name kann zu Konflikten mit zukünftigen Systemprozeduren führen. [...]

Über Leistungsprobleme, die durch das Präfix sp_ verursacht werden, wird dort jedoch nichts erwähnt. Ich würde gerne wissen, ob dies immer noch der Fall ist oder ob es nach SQL Server 2000 behoben wurde.

Wie Martin Smiths einfacher Kommentar zeigt - Ja, wenn Sie eine gespeicherte Prozedur mit einem sp_Präfix haben -, überprüft der SQL Server-Abfrage-Executor immermaster zuerst die Datenbank, um festzustellen, ob eine gespeicherte Prozedur (die als gespeicherte Systemprozedur gekennzeichnet ist) mit diesem Namen vorhanden ist.

Und wenn es existiert, hat diese gespeicherte Systemprozedur aus der masterDatenbank immer Vorrang und wird anstelle Ihrer eigenen ausgeführt.

Also ja - es steht immer noch: Verwenden Sie nicht das sp_Präfix.

marc_s
quelle
5
Einfach zu testen. CREATE PROC dbo.sp_helptext AS SELECT 1dann versuchenEXEC dbo.sp_helptext
Martin Smith
Vielen Dank für Ihre Antwort, eine sehr nützliche Ergänzung zur Verbreitung von masterSPs.
2

Ein besserer Test besteht darin, eine Abfrage zu schreiben, die eine vollständige Optimierung erfordert, da dies wahrscheinlich eine bessere Reflektion dessen ist, was der von Ihnen geschriebene Prozess tut. Ich habe die folgende Abfrage in einen SP eingeschlossen, Ihren Test wiederholt und die gleichen Ergebnisse erhalten.

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

Ich habe in beiden Fällen die gleiche Anzahl an Cache-Miss- und -Hit-Ereignissen erhalten, und in beiden Fällen wurde der Plan dem Cache hinzugefügt. Ich habe auch beide Prozesse mehrmals ausgeführt und es gab keinen konsistenten Unterschied in der CPU-Zeit oder der verstrichenen Zeit, der von dm_exec_query_stats gemeldet wurde.

Die andere Sorge ist, dass, da "sp_" -Prozesse vom Master ausgeführt werden können, Sie möglicherweise eine Kopie des Prozesses erhalten, der in den Master anstelle der Datenbank, in der Sie arbeiten, ausgeführt wurde, aber ein schneller Test wird zeigen, dass dies nicht der Fall ist. Wenn der Prozess jedoch aus der Datenbank gelöscht wird, in der Sie arbeiten, und eine Kopie im Master vorhanden ist, wird er ausgeführt, was ein Problem sein kann, wenn es sich um eine alte Version handelt. Wenn dies ein Problem ist, würde ich nicht "sp_" verwenden, um den Proc zu benennen.

cfradenburg
quelle
Interessante Funde, danke! Ich werde Ihr Beispiel in Kombination mit Aarons Beispiel verwenden , um weitere Tests durchzuführen.
1

Ich glaube, dass das Problem zu tun hat, wenn Sie den vollständig qualifizierten Objektnamen nicht angeben. "EXEC sp_something" prüft also zuerst den Master, "EXEC dbname.dbo.sp_something" geht jedoch niemals zuerst an den Master.

Wenn ich mich recht erinnere, besteht die Lektion darin, immer den vollständig qualifizierten Namen zu verwenden.

SQLRockstar
quelle
5
Denken Sie nicht, dass das einen Unterschied macht. EXEC MyDB.dbo.sp_helptext 'sp_helptext'verwendet immer noch die von, masterauch wenn es eine in der Benutzerdatenbank gibt. AFAIK überprüft beide Standorte und verwendet den Standort, von dem masterer existiert und als Systemobjekt markiert ist.
Martin Smith
1
@MartinSmith im Jahr 2012 Ich konnte die auszuführende Masterversion nicht erzwingen (obwohl meine Tests dort gezeigt haben, dass etwas los ist), es sei denn, ich habe die lokale Kopie gelöscht (in diesem Fall wurde die Masterversion MyDB.dbo.sp_foonoch ausgeführt). Ich habe 2008/2008 R2 derzeit nicht, um zu bestätigen, wo sich dieses Verhalten geändert hat.
Aaron Bertrand
@ AaronBertrand - Ah, interessant, ich habe meinen Test auf 2008 R2 gemacht.
Martin Smith
Beachten Sie auch, dass wenn eine lokale Prozedur nicht gefunden wird und eine im Master gefunden wird, diese ausgeführt wird und dafür nicht als Systemobjekt markiert werden muss. Und zumindest im Jahr 2012 ändert sich das Verhalten nicht, wenn die Masterkopie als Systemobjekt markiert ist oder nicht. Mit oder ohne lokales DB / Schema-Präfix wird die lokale Kopie immer ausgeführt, sofern sie nicht vorhanden ist.
Aaron Bertrand
1
Hoppla, ich hätte klarstellen sollen, dass mein Kommentar auf die vorgeschlagene Antwort abzielte. SQLRockstars Kommentar "EXEC dbname.dbo.sp_something wird niemals zuerst zum Master." ist falsch.
Greenstone Walker