Ancora sbagliato a iniziare il nome di una procedura memorizzata dall'utente con sp_?


33

Uno dei miei colleghi ha chiamato una procedura memorizzata nel nostro database SQL Server 2008 R2 sp_something. Quando ho visto questo, ho subito pensato: "È SBAGLIATO!" e ho iniziato a cercare nei miei segnalibri questo articolo online che spiega perché è sbagliato, così ho potuto fornire una spiegazione al mio collega.

Nell'articolo (di Brian Moran ) viene spiegato che assegnando alla procedura memorizzata un prefisso sp_ , SQL Server esamina il database master per un piano compilato. Poiché sp_sprocnon si trova lì, SQL Server ricompilerà la procedura (e per questo richiede un blocco di compilazione esclusivo, causando problemi di prestazioni).

Il seguente esempio è riportato nell'articolo per mostrare la differenza tra due procedure:

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

Eseguire questo, quindi aprire il Profiler (aggiungere l' SP:CacheMissevento Stored Procedures -> ) ed eseguire nuovamente le stored procedure. Dovresti vedere una differenza tra le due stored procedure: la sp_Select1stored procedure genererà un SP:CacheMissevento in più rispetto alla Select1stored procedure (l'articolo fa riferimento a SQL Server 7.0 e SQL Server 2000 ).

Quando eseguo l'esempio nel mio ambiente SQL Server 2008 R2, ottengo la stessa quantità di SP:CacheMisseventi per entrambe le procedure (sia in tempdb che in un altro database di test).

Quindi mi chiedo:

  • Posso aver fatto qualcosa di sbagliato nell'esecuzione dell'esempio?
  • sproc sp_somethingL'adagium " non nominare un utente " è ancora valido nelle versioni più recenti di SQL Server?
  • In tal caso, esiste un buon esempio che mostra la sua validità in SQL Server 2008 R2?

Grazie mille per i tuoi pensieri su questo!

MODIFICARE

Ho trovato Creazione di stored procedure (Motore di database) su msdn per SQL Server 2008 R2, che risponde alla mia seconda domanda:

Si consiglia di non creare alcuna procedura memorizzata utilizzando sp_ come prefisso. SQL Server utilizza il prefisso sp_ per designare le stored procedure di sistema. Il nome scelto potrebbe essere in conflitto con alcune future procedure di sistema. [...]

Non viene menzionato nulla in merito ai problemi di prestazioni causati dall'utilizzo del sp_prefisso. Mi piacerebbe sapere se è ancora così o se lo hanno risolto dopo SQL Server 2000.


3
Ho già esaminato questo aspetto e ho riscontrato una differenza di prestazioni trascurabile che ho ridotto leggermente al sovraccarico della risoluzione delle sp_versioni (è necessario controllare sia i database master che quelli utente perché dà la priorità ai proc di sistema in master-> proc in DB utente -> non di sistema procs in master)
Martin Smith,

4
Che vantaggio vedi per il prefisso di una stored procedure con sp_? È utile quanto il prefisso di una tabella con tbl. Perché fare prima il master di ricerca del sistema (anche se è trascurabile o nessuna differenza di prestazioni) per consentire di utilizzare questa convenzione di denominazione insignificante?
Aaron Bertrand

1
@AaronBertrand: ad essere onesti, non vedo alcun beneficio a tutti in anteponendo sprocs con sp_, solo svantaggi, e non avrei mai anteporre loro in questo modo io stesso. Ma voglio tutti gli argomenti che posso ottenere per convincere i miei colleghi a non farlo neanche.

1
Sì, tbl è inutile, ma mi piace ancora usarlo. Dev'essere il mio disturbo ossessivo compulsivo a entrare. Adesso scendi dal mio prato.
SQLRockstar,

1
@Josien, anche i tuoi colleghi dovrebbero presentare argomenti per rendere più complicato uno schema di denominazione. Fagli spiegare perché dbo.sp_Author_Renameè meglio di dbo.Author_Rename. Non riesco a pensare a una sola cosa che abbia senso.
Aaron Bertrand

Risposte:


31

È abbastanza facile metterti alla prova. Creiamo due procedure molto semplici:

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

Ora costruiamo un wrapper che li esegua più volte, con e senza il prefisso dello schema:

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

risultati:

inserisci qui la descrizione dell'immagine

conclusioni:

  • l'utilizzo del prefisso sp_ è più lento
  • tralasciando il prefisso dello schema è più lento

La domanda più importante: perché si vuole utilizzare il prefisso sp_? Che cosa i vostri collaboratori si aspettano di guadagnare dal farlo? Ciò non dovrebbe riguardare la necessità di dimostrare che ciò è peggio, ma dovrebbe giustificare l'aggiunta dello stesso prefisso di tre lettere a ogni singola procedura memorizzata nel sistema. Non riesco a vedere il vantaggio.

Inoltre ho eseguito alcuni test piuttosto estesi di questo modello nel seguente post di blog:

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


Nota, questi risultati sono su SQL Server 2012. Ma puoi eseguire gli stessi test nel tuo ambiente.
Aaron Bertrand

1
"Che cosa si aspettano di guadagnare dai tuoi collaboratori" vedi anche Notazione ungherese . Fondamentalmente, è una cosa degli anni '90 per la maggior parte. Inoltre, nel mio lavoro precedente lo standard era quello di anteporre a ogni procedura memorizzata in sp_modo che potessero essere differenziate da altre cose e senza conflitti di nomi ... Non avevo idea che questo problema di prestazioni esistesse con esso.
Earlz,

Ottimo esempio, grazie Aaron. Lo sto ancora testando su 2008 R2 (e probabilmente testandolo nel modo sbagliato, perché 'dbo.wrapper_sp1' e 'dbo.wrapper_sp2' sembrano significativamente più veloci degli altri due in questo momento).

12

Si consiglia di non creare alcuna procedura memorizzata utilizzando sp_ come prefisso. SQL Server utilizza il prefisso sp_ per designare le stored procedure di sistema. Il nome scelto potrebbe essere in conflitto con alcune future procedure di sistema. [...]

Non viene menzionato nulla in merito ai problemi di prestazioni causati dall'utilizzo del prefisso sp_. Mi piacerebbe sapere se è ancora così o se lo hanno risolto dopo SQL Server 2000.

Come mostra il semplice commento di Martin Smith - sì, se si dispone di una procedura memorizzata con un sp_prefisso - l'esecutore di query di SQL Server controllerà sempremaster prima nel database se esiste una procedura memorizzata (contrassegnata come procedura memorizzata dal sistema) con quel nome.

E se esiste, quella procedura memorizzata dal sistema dal masterdatabase prevale sempre e verrà eseguita al posto della tua.

Quindi sì - è ancora valido: non usare il sp_prefisso.


5
Semplice da testare. CREATE PROC dbo.sp_helptext AS SELECT 1quindi provaEXEC dbo.sp_helptext
Martin Smith,

Grazie per la risposta, aggiunta molto utile sulla prevalenza di mastersp.

2

Un test migliore è quello di scrivere una query che richiede un'ottimizzazione completa poiché è probabilmente un riflesso migliore di ciò che sta facendo il proc che stai scrivendo. Ho racchiuso la seguente query in un SP, ripetuto il test e ottenuto gli stessi risultati.

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

Ho avuto lo stesso numero di eventi cache mancati e hit in entrambi i casi e in entrambi i casi il piano è stato aggiunto alla cache. Ho anche eseguito entrambi i processi più volte e non vi era alcuna differenza costante nel tempo della CPU o nel tempo trascorso riportato da dm_exec_query_stats.

L'altra preoccupazione è che dal momento che "sp_" procs può essere eseguito dal master, è possibile ottenere una copia del proc che è stato eseguito nel master invece del DB in cui si sta lavorando, ma un test rapido mostrerà che non è il caso. Tuttavia, se proc viene eliminato dal DB in cui si sta lavorando ed esiste una copia nel master, verrà eseguito il che potrebbe essere un problema se si tratta di una versione precedente. Se questa è una preoccupazione non userei "sp_" per nominare il proc.


Ritrovamenti interessanti, grazie! Userò il tuo esempio in combinazione con l'esempio di Aaron per eseguire altri test.

1

Credo che il problema abbia a che fare quando non si specifica il nome completo dell'oggetto. Pertanto, "EXEC sp_something" controllerà prima il master, ma "EXEC dbname.dbo.sp_something" non andrà mai prima al master.

La lezione, se ricordo, è di usare sempre il nome completo.


5
Non pensare che faccia alcuna differenza. EXEC MyDB.dbo.sp_helptext 'sp_helptext'usa ancora quello di masteranche se ce n'è uno nel database degli utenti. AFAIK controlla entrambe le posizioni e utilizzerà quella da masterse esiste ed è contrassegnata come oggetto di sistema.
Martin Smith,

1
@MartinSmith nel 2012 non ho potuto forzare l'esecuzione della versione principale (anche se i miei test hanno mostrato che c'è qualcosa in corso), a meno che non abbia lasciato cadere la copia locale (nel qual caso è MyDB.dbo.sp_fooancora stata eseguita la versione principale). Non ho 2008/2008 R2 in questo momento per confermare dove è cambiato questo comportamento.
Aaron Bertrand

@AaronBertrand - Ah, interessante ho fatto il mio test sul 2008 R2.
Martin Smith,

Si noti inoltre che se non viene trovata una procedura locale e ne viene trovata una nel master, quest'ultima verrà eseguita e non è necessario contrassegnarla come oggetto di sistema affinché ciò avvenga. E almeno nel 2012, indipendentemente dal fatto che la copia master sia contrassegnata come oggetto di sistema, non cambia il comportamento - con o senza prefisso db / schema locale, la copia locale viene sempre eseguita a meno che non esista.
Aaron Bertrand

1
Spiacenti, avrei dovuto chiarire che il mio commento era diretto alla risposta suggerita. Il commento di SQLRockstar "EXEC dbname.dbo.sp_something non andrà mai prima al master." non è corretto.
Greenstone Walker,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.