Toujours pas le bon pour commencer le nom d'une procédure stockée utilisateur avec sp_?

33

Un de mes collègues a nommé une procédure stockée dans notre base de données SQL Server 2008 R2 sp_something. Quand j'ai vu cela, j'ai immédiatement pensé: "C'est FAUX!" et a commencé à chercher dans mes signets cet article en ligne qui explique pourquoi il est faux, afin que je puisse fournir une explication à mon collègue.

Dans l'article (de Brian Moran ), il est expliqué que, si un préfixe sp_ est attribué à la procédure stockée, SQL Server recherche dans la base de données master un plan compilé. sp_sprocSQL Server recompilera la procédure ( car elle n’y réside pas) (et nécessite un verrou de compilation exclusif pour cela, ce qui entraîne des problèmes de performances).

L'exemple suivant est donné dans l'article pour montrer la différence entre deux procédures:

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

Vous exécutez cette opération, puis ouvrez le profileur (ajoutez l' SP:CacheMissévénement Procédures stockées -> ) et exécutez à nouveau les procédures stockées. Vous êtes censé voir une différence entre les deux procédures stockées: la sp_Select1procédure stockée générera un SP:CacheMissévénement de plus que la Select1procédure stockée (l'article fait référence à SQL Server 7.0 et SQL Server 2000 ).

Lorsque j'exécute l'exemple dans mon environnement SQL Server 2008 R2, j'obtiens le même nombre d' SP:CacheMissévénements pour les deux procédures (à la fois dans tempdb et dans une autre base de données de test).

Alors je me demande:

  • Puis-je avoir fait quelque chose de mal dans l'exécution de l'exemple?
  • L' sproc sp_somethingadagium " ne nommez-vous pas un utilisateur " est-il toujours valable dans les versions les plus récentes de SQL Server?
  • Si tel est le cas, existe-t-il un bon exemple montrant sa validité dans SQL Server 2008 R2?

Merci beaucoup pour vos réflexions à ce sujet!

MODIFIER

J'ai trouvé la création de procédures stockées (moteur de base de données) sur msdn pour SQL Server 2008 R2, ce qui répond à ma deuxième question:

Nous vous recommandons de ne créer aucune procédure stockée utilisant sp_ comme préfixe. SQL Server utilise le préfixe sp_ pour désigner les procédures stockées du système. Le nom que vous choisissez peut entrer en conflit avec une procédure système future. [...]

Rien n’y est fait mention des problèmes de performances causés par l’utilisation du sp_préfixe. J'aimerais savoir si c'est toujours le cas ou s'ils l'ont corrigé après SQL Server 2000.

marc_s
la source
3
J'y ai déjà jeté un coup d'œil et constaté une différence de performances négligeable, que j'ai imputée à un temps système de résolution des sp_versions légèrement supérieur (il faut archiver les bases de données maître et utilisateur, car il priorise les processus système dans master-> procs dans la base de données utilisateur -> non système Procs dans master)
Martin Smith
4
Quel avantage voyez-vous à préfixer une procédure stockée sp_? C'est à peu près aussi utile que de préfixer une table avec tbl. Pourquoi faire d'abord de la recherche système (même si la différence de performances est négligeable ou nulle) pour vous permettre d'utiliser cette convention de dénomination sans signification?
Aaron Bertrand
1
@AaronBertrand: pour être honnête, je ne vois aucun avantage à préfixer les sprocs avec sp_, mais uniquement des inconvénients, et je ne les préfixerais jamais de cette façon. Mais je veux tous les arguments possibles pour convaincre mes collègues de ne pas le faire non plus.
1
Oui, tbl est inutile, mais j'aime toujours l'utiliser. Ce doit être mon TOC qui entre en jeu. Maintenant, lâche-moi.
SQLRockstar
1
@ Josien également, vos collègues devraient présenter des arguments pour rendre un schéma de nommage plus compliqué. Demandez-leur d'expliquer pourquoi dbo.sp_Author_Renameest mieux que dbo.Author_Rename. Je ne peux pas penser à une seule chose qui a du sens.
Aaron Bertrand

Réponses:

31

C'est assez facile de vous tester. Créons deux procédures très simples:

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

Construisons maintenant un wrapper qui les exécute plusieurs fois, avec et sans le préfixe du schéma:

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

Résultats:

entrez la description de l'image ici

Conclusions:

  • l'utilisation du préfixe sp_ est plus lente
  • laisser le préfixe du schéma plus lent

La question plus importante: pourquoi voudriez - vous voulez utiliser le préfixe sp_? Qu'est-ce que vos collègues attendent à gagner de le faire? Cela ne devrait pas vous obliger à prouver que c'est pire, mais plutôt à justifier de l'ajout du même préfixe de trois lettres à chaque procédure stockée dans le système. Je ne vois pas le bénéfice.

J'ai également effectué des tests assez poussés sur ce modèle dans l'article suivant du blog:

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

Aaron Bertrand
la source
Notez que ces résultats sont sur SQL Server 2012. Mais vous pouvez effectuer les mêmes tests dans votre environnement.
Aaron Bertrand
1
"Qu'attendent vos collègues de travail?" Voir aussi Notation hongroise . Fondamentalement, c'est une chose des années 90 pour la plupart. En outre, dans mon travail précédent, la norme consistait à préfixer chaque procédure stockée sp_afin de pouvoir la différencier des autres éléments et éviter tout conflit de nom ... Je ne savais pas que ce problème de performances existait.
Earlz
Excellent exemple, merci Aaron. Je le teste toujours sur 2008 R2 (et probablement dans le mauvais sens, car "dbo.wrapper_sp1" et "dbo.wrapper_sp2" semblent nettement plus rapides que les deux autres actuellement).
12

Nous vous recommandons de ne créer aucune procédure stockée utilisant sp_ comme préfixe. SQL Server utilise le préfixe sp_ pour désigner les procédures stockées du système. Le nom que vous choisissez peut entrer en conflit avec une procédure système future. [...]

Rien n’y est fait mention des problèmes de performances causés par l’utilisation du préfixe sp_. J'aimerais savoir si c'est toujours le cas ou s'ils l'ont corrigé après SQL Server 2000.

Comme le montre le simple commentaire de Martin Smith - oui, si vous avez une procédure stockée avec un sp_préfixe - l'exécuteur de la requête SQL Server vérifie toujours dans la masterbase de données s'il existe une procédure stockée (marquée comme procédure stockée système) portant ce nom.

Et si elle existe, cette procédure stockée système de la masterbase de données prévaut toujours et sera exécutée à la place de la vôtre.

Alors oui, cela reste: n'utilisez pas le sp_préfixe.

marc_s
la source
5
Simple à tester. CREATE PROC dbo.sp_helptext AS SELECT 1puis essayezEXEC dbo.sp_helptext
Martin Smith
Merci pour votre réponse, ajout très utile sur la prévalence des mastersp.
2

Un meilleur test consiste à rédiger une requête qui nécessite une optimisation complète, car cela reflète probablement mieux ce que fait le proc que vous écrivez. J'ai enveloppé la requête suivante dans un SP et répété votre test et obtenu les mêmes résultats.

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

J'ai eu le même nombre d'événements manqués et touchés dans le cache dans les deux cas et dans les deux cas, le plan a été ajouté au cache. J'ai également exécuté les deux procs plusieurs fois et il n'y avait aucune différence cohérente dans le temps CPU ou le temps écoulé signalé par dm_exec_query_stats.

L'autre préoccupation est que, puisque les procédures "sp_" peuvent être exécutées à partir du maître, vous pouvez obtenir une copie du processus exécuté dans maître au lieu de la base de données sur laquelle vous travaillez, mais un test rapide montrera que ce n'est pas le cas. Cependant, si le processus est supprimé de la base de données dans laquelle vous travaillez et qu'une copie existe en maître, il sera exécuté, ce qui pourrait poser problème s'il s'agit d'une ancienne version. Si cela pose problème, je n’utiliserais pas «sp_» pour nommer le proc.

cfradenburg
la source
Des trouvailles intéressantes, merci! J'utiliserai votre exemple en combinaison avec l'exemple d' Aaron pour effectuer d'autres tests.
1

Je pense que le problème doit être résolu lorsque vous ne spécifiez pas le nom d'objet pleinement qualifié. Donc, "EXEC sp_something" vérifie d'abord le maître, mais "EXEC dbname.dbo.sp_something" ne sera jamais traité en premier.

La leçon, si je me souviens bien, est d'utiliser toujours le nom complet.

SQLRockstar
la source
5
Ne pensez pas que cela fait une différence. EXEC MyDB.dbo.sp_helptext 'sp_helptext'utilise toujours celui de, mastermême s’il en existe un dans la base de données des utilisateurs. Autant que je sache, il vérifie les deux emplacements et utilisera celui de masters'il existe et est marqué comme objet système.
Martin Smith
1
@MartinSmith 2012, je ne pouvais pas forcer la version principale à être exécutée (bien que mes tests aient montré qu'il se passait quelque chose ), à moins que je ne lâche la copie locale (dans ce cas, MyDB.dbo.sp_fooj'exécutais encore la version principale). Je n'ai pas 2008/2008 R2 pour le moment pour confirmer en quoi ce comportement a changé.
Aaron Bertrand
@AaronBertrand - Ah, intéressant, j'ai fait mon test sur 2008 R2.
Martin Smith
Notez également que si une procédure locale n’est pas trouvée et qu’elle se trouve dans le maître, celle-ci sera exécutée et n’a pas besoin d’être marquée en tant qu’objet système pour que cela se produise. Et en 2012 au moins, que la copie principale soit marquée ou non comme objet système ne change pas le comportement - avec ou sans préfixe de base / schéma local, la copie locale est toujours exécutée, sauf si elle n'existe pas.
Aaron Bertrand
1
Oups, j'aurais dû préciser que mon commentaire visait la réponse suggérée. Commentaire de SQLRockstar "EXEC dbname.dbo.sp_something n'ira jamais au premier maître." est incorrect.
Greenstone Walker