In der SQL Server-Welt gibt es zwei Arten von Menschen:diejenigen, die es mögen, wenn alle ihre Objekte mit Präfixen versehen werden, und diejenigen, die dies nicht tun. Die erstere Gruppe wird weiter in zwei Kategorien unterteilt:diejenigen, die gespeicherten Prozeduren sp_
voranstellen , und diejenigen, die andere Präfixe wählen (wie usp_
oder proc_
). Eine langjährige Empfehlung lautet, sp_
zu vermeiden Präfix, sowohl aus Leistungsgründen als auch um Mehrdeutigkeiten oder Kollisionen zu vermeiden, wenn Sie zufällig einen Namen auswählen, der bereits im Systemkatalog vorhanden ist. Kollisionen sind sicherlich immer noch ein Problem, aber vorausgesetzt, Sie haben Ihren Objektnamen überprüft, ist es immer noch ein Leistungsproblem?
TL;DR-Version:JA.
Das Präfix sp_ ist immer noch tabu. Aber in diesem Beitrag werde ich erklären, warum, wie SQL Server 2012 Sie glauben machen könnte, dass dieser Warnhinweis nicht mehr gilt, und einige andere mögliche Nebenwirkungen der Wahl dieser Namenskonvention.
Was ist das Problem mit sp_?
Der sp_
Präfix bedeutet nicht, was Sie denken:Die meisten Leute denken an sp
steht für "gespeicherte Prozedur", obwohl es eigentlich "speziell" bedeutet. Gespeicherte Prozeduren (sowie Tabellen und Ansichten), die im Master mit einem sp_
gespeichert sind Präfix sind von jeder Datenbank ohne richtige Referenz zugänglich (vorausgesetzt, es existiert keine lokale Version). Wenn die Prozedur als Systemobjekt markiert ist (mithilfe von sp_MS_marksystemobject
(eine undokumentierte und nicht unterstützte Systemprozedur, die is_ms_shipped
setzt auf 1), dann wird die Prozedur im Master im Kontext der aufrufenden Datenbank ausgeführt. Schauen wir uns ein einfaches Beispiel an:
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 GOzurück
Ergebnisse:
(0 row(s) affected) sp_test foo (1 row(s) affected)
Das Leistungsproblem ergibt sich aus der Tatsache, dass der Master möglicherweise auf eine äquivalente gespeicherte Prozedur überprüft wird, je nachdem, ob eine lokale Version der Prozedur vorhanden ist und ob tatsächlich ein äquivalentes Objekt im Master vorhanden ist. Dies kann zu zusätzlichem Metadaten-Overhead sowie zu einem zusätzlichen SP:CacheMiss
führen Veranstaltung. Die Frage ist, ob dieser Overhead greifbar ist.
Betrachten wir also eine sehr einfache Prozedur in einer Testdatenbank:
CREATE DATABASE sp_prefix; GO USE sp_prefix; GO CREATE PROCEDURE dbo.sp_something AS BEGIN SELECT 'sp_prefix', DB_NAME(); END GO
Und gleichwertige Verfahren im Master:
USE master; GO CREATE PROCEDURE dbo.sp_something AS BEGIN SELECT 'master', DB_NAME(); END GO EXEC sp_MS_marksystemobject N'sp_something';
CacheMiss:Tatsache oder Fiktion?
Wenn wir einen Schnelltest von unserer Testdatenbank aus ausführen, sehen wir, dass die Ausführung dieser gespeicherten Prozeduren niemals die Versionen von master tatsächlich aufrufen wird, unabhängig davon, ob wir die Prozedur ordnungsgemäß Datenbank- oder Schema-qualifizieren (ein häufiges Missverständnis) oder ob wir die markieren Masterversion als Systemobjekt:
USE sp_prefix; GO EXEC sp_prefix.dbo.sp_something; GO EXEC dbo.sp_something; GO EXEC sp_something;
Ergebnisse:
sp_prefix sp_prefix sp_prefix sp_prefix sp_prefix sp_prefix
Lassen Sie uns auch einen Quick TraceSP:CacheMiss
gibt Veranstaltungen:
Wir sehen CacheMiss
Ereignisse für den Ad-hoc-Stapel, der die gespeicherte Prozedur aufruft (da SQL Server sich im Allgemeinen nicht darum kümmert, einen Stapel zwischenzuspeichern, der hauptsächlich aus Prozeduraufrufen besteht), aber nicht für die gespeicherte Prozedur selbst. Sowohl mit als auch ohne sp_something
Prozedur, die im Master vorhanden ist (und wenn sie existiert, sowohl mit als auch ohne Markierung als Systemobjekt), die Aufrufe von sp_something
Rufen Sie in der Benutzerdatenbank niemals "versehentlich" die Prozedur in master auf und erzeugen Sie niemals CacheMiss
Ereignisse für das Verfahren.
Dies war auf SQL Server 2012. Ich habe die gleichen Tests oben auf SQL Server 2008 R2 wiederholt und etwas andere Ergebnisse gefunden:
Auf SQL Server 2008 R2 sehen wir also eine zusätzliche CacheMiss
Ereignis, das in SQL Server 2012 nicht auftritt. Dies tritt in allen Szenarios auf (kein äquivalenter Objektmaster, ein Objekt im Master, das als Systemobjekt markiert ist, und ein Objekt im Master, das nicht als Systemobjekt markiert ist). Ich war sofort gespannt, ob dieses zusätzliche Ereignis spürbare Auswirkungen auf die Leistung haben würde.
Leistungsproblem:Tatsache oder Fiktion?
Ich habe eine zusätzliche Prozedur ohne den sp_
gemacht Präfix zum Vergleich der Rohleistung, CacheMiss
beiseite:
USE sp_prefix; GO CREATE PROCEDURE dbo.proc_something AS BEGIN SELECT 'sp_prefix', DB_NAME(); END GO
Der einzige Unterschied zwischen sp_something
und proc_something
. Ich habe dann Wrapper-Prozeduren erstellt, um sie jeweils 1000 Mal auszuführen, indem ich EXEC sp_prefix.dbo.<procname>
verwendet habe , EXEC dbo.<procname>
und EXEC <procname>
Syntax, wobei äquivalente gespeicherte Prozeduren im Master leben und als Systemobjekt markiert sind, im Master leben, aber nicht als Systemobjekt markiert sind und überhaupt nicht im Master leben.
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
Die Messung der Laufzeitdauer jeder Wrapper-Prozedur mit dem SQL Sentry Plan Explorer zeigt, dass die Verwendung von sp_
Präfix hat in fast allen Fällen (und sicherlich im Durchschnitt) einen erheblichen Einfluss auf die durchschnittliche Dauer: