sql >> Database >  >> RDS >> Database

Is het voorvoegsel sp_ nog steeds een nee-nee?

In de SQL Server-wereld zijn er twee soorten mensen:zij die graag al hun objecten vooraf laten gaan, en zij die dat niet doen. De eerste groep is verder onderverdeeld in twee categorieën:degenen die opgeslagen procedures voorafgaan met sp_ , en degenen die andere voorvoegsels kiezen (zoals usp_ of proc_ ). Een al lang bestaande aanbeveling is om de sp_ . te vermijden prefix, zowel om prestatieredenen als om dubbelzinnigheid of botsingen te voorkomen als u een naam kiest die al in de systeemcatalogus bestaat. Botsingen zijn zeker nog steeds een probleem, maar ervan uitgaande dat u uw objectnaam hebt doorgelicht, is het dan nog steeds een prestatieprobleem?

TL;DR-versie:JA.

Het voorvoegsel sp_ is nog steeds een nee-nee. Maar in dit bericht zal ik uitleggen waarom, hoe SQL Server 2012 u zou kunnen doen geloven dat dit waarschuwende advies niet langer van toepassing is, en enkele andere mogelijke bijwerkingen van het kiezen van deze naamgevingsconventie.

Wat is het probleem met sp_?

De sp_ voorvoegsel betekent niet wat je denkt dat het doet:de meeste mensen denken sp staat voor "opgeslagen procedure" terwijl het in feite "speciaal" betekent. Opgeslagen procedures (evenals tabellen en views) opgeslagen in master met een sp_ prefix zijn toegankelijk vanuit elke database zonder een juiste verwijzing (ervan uitgaande dat er geen lokale versie bestaat). Als de procedure is gemarkeerd als een systeemobject (met behulp van sp_MS_marksystemobject (een ongedocumenteerde en niet-ondersteunde systeemprocedure die is_ms_shipped instelt naar 1), dan wordt de procedure in master uitgevoerd in de context van de aanroepende database. Laten we een eenvoudig voorbeeld bekijken:

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
GO

Resultaten:

(0 row(s) affected)

sp_test    foo

(1 row(s) affected)

Het prestatieprobleem komt van het feit dat master kan worden gecontroleerd op een equivalente opgeslagen procedure, afhankelijk van of er een lokale versie van de procedure is en of er in feite een equivalent object in master is. Dit kan leiden tot extra metadata-overhead en een extra SP:CacheMiss evenement. De vraag is of deze overhead voelbaar is.

Laten we dus een heel eenvoudige procedure in een testdatabase bekijken:

CREATE DATABASE sp_prefix;
GO
USE sp_prefix;
GO
CREATE PROCEDURE dbo.sp_something
AS
BEGIN
  SELECT 'sp_prefix', DB_NAME();
END
GO

En gelijkwaardige procedures in 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:feit of fictie?

Als we een snelle test uitvoeren vanuit onze testdatabase, zien we dat het uitvoeren van deze opgeslagen procedures nooit de versies van de master zal oproepen, ongeacht of we de procedure correct kwalificeren voor de database of het schema (een veelvoorkomende misvatting) of dat we de masterversie als systeemobject:

USE sp_prefix;
GO
EXEC sp_prefix.dbo.sp_something;
GO
EXEC dbo.sp_something;
GO
EXEC sp_something;

Resultaten:

sp_prefix    sp_prefix
sp_prefix    sp_prefix
sp_prefix    sp_prefix

Laten we ook een Quick Trace uitvoeren® SQL Sentry gebruiken om te zien of er SP:CacheMiss . zijn evenementen:

We zien CacheMiss gebeurtenissen voor de ad-hocbatch die de opgeslagen procedure aanroept (aangezien SQL Server over het algemeen niet de moeite neemt om een ​​batch in de cache te plaatsen die voornamelijk uit procedureaanroepen bestaat), maar niet voor de opgeslagen procedure zelf. Zowel met als zonder de sp_something procedure die in master bestaat (en wanneer deze bestaat, zowel met als zonder dat deze is gemarkeerd als een systeemobject), de aanroepen van sp_something in de gebruikersdatabase nooit "per ongeluk" de procedure in master aanroepen, en nooit een CacheMiss genereren gebeurtenissen voor de procedure.

Dit was op SQL Server 2012. Ik herhaalde dezelfde tests hierboven op SQL Server 2008 R2 en vond iets andere resultaten:

Dus op SQL Server 2008 R2 zien we een extra CacheMiss gebeurtenis die niet voorkomt in SQL Server 2012. Dit gebeurt in alle scenario's (geen equivalent objectmaster, een object in master gemarkeerd als systeemobject en een object in master dat niet is gemarkeerd als systeemobject). Ik was meteen benieuwd of deze extra gebeurtenis een merkbare impact zou hebben op de prestaties.

Prestatieprobleem:feit of fictie?

Ik heb een extra procedure gemaakt zonder de sp_ prefix om onbewerkte prestaties te vergelijken, CacheMiss terzijde:

USE sp_prefix;
GO
CREATE PROCEDURE dbo.proc_something
AS
BEGIN
  SELECT 'sp_prefix', DB_NAME();
END
GO

Dus het enige verschil tussen sp_something en proc_something . Ik heb vervolgens wrapper-procedures gemaakt om ze elk 1000 keer uit te voeren, met behulp van EXEC sp_prefix.dbo.<procname> , EXEC dbo.<procname> en EXEC <procname> syntaxis, met equivalente opgeslagen procedures die leven in master en gemarkeerd als een systeemobject, leven in master maar niet gemarkeerd als een systeemobject, en helemaal niet leven in master.

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

Door de runtime-duur van elke wrapper-procedure te meten met SQL Sentry Plan Explorer, blijkt uit de resultaten dat het gebruik van de sp_ prefix heeft in bijna alle gevallen (en zeker gemiddeld) een significante impact op de gemiddelde duur: