Um dos meus colegas de trabalho nomeou um procedimento armazenado em nosso banco de dados SQL Server 2008 R2 sp_something
. Quando vi isso, pensei imediatamente: "Está errado!" e comecei a pesquisar nos meus favoritos este artigo on-line que explica por que está errado, para que eu pudesse fornecer uma explicação ao meu colega de trabalho.
No artigo (de Brian Moran ), é explicado que atribuir ao procedimento armazenado um prefixo sp_ faz com que o SQL Server procure no banco de dados mestre um plano compilado. Como o sp_sproc
arquivo não reside lá, o SQL Server recompilará o procedimento (e precisará de um bloqueio de compilação exclusivo para isso, causando problemas de desempenho).
O exemplo a seguir é fornecido no artigo para mostrar a diferença entre dois procedimentos:
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
Você executa isso, abra o Profiler (adicione o SP:CacheMiss
evento Stored Procedures -> ) e execute os procedimentos armazenados novamente. Você deve ver uma diferença entre os dois procedimentos armazenados: o sp_Select1
procedimento armazenado gerará mais um SP:CacheMiss
evento que o Select1
procedimento armazenado (o artigo faz referência ao SQL Server 7.0 e SQL Server 2000 ).
Quando executo o exemplo no meu ambiente do SQL Server 2008 R2, recebo a mesma quantidade de SP:CacheMiss
eventos para os dois procedimentos (no tempdb e em outro banco de dados de teste).
Então, eu estou pensando:
- Posso ter feito algo errado na execução do exemplo?
Osproc sp_something
adágio ' não nomear um usuário ' ainda é válido nas versões mais recentes do SQL Server?- Em caso afirmativo, existe um bom exemplo que mostra sua validade no SQL Server 2008 R2?
Muito obrigado por seus pensamentos sobre isso!
EDITAR
Encontrei Criando procedimentos armazenados (mecanismo de banco de dados) no msdn para SQL Server 2008 R2, que responde minha segunda pergunta:
Recomendamos que você não crie procedimentos armazenados usando sp_ como prefixo. O SQL Server usa o prefixo sp_ para designar procedimentos armazenados do sistema. O nome escolhido pode entrar em conflito com algum procedimento futuro do sistema. [...]
Nada é mencionado lá sobre problemas de desempenho causados pelo uso do sp_
prefixo. Gostaria de saber se esse ainda é o caso ou se eles o corrigiram após o SQL Server 2000.
sp_
versões (precisa verificar os bancos de dados mestre e de usuário porque prioriza os procs do sistema emmaster
-> procs no usuário DB -> não sistema procs inmaster
)sp_
? Isso é tão útil quanto prefixar uma tabela comtbl
. Por que tornar a pesquisa do sistema principal primeiro (mesmo que seja insignificante ou sem diferença de desempenho) para permitir que você use essa convenção de nomenclatura sem sentido?dbo.sp_Author_Rename
é melhor quedbo.Author_Rename
. Não consigo pensar em nada que faça sentido.Respostas:
Isso é bastante fácil de se testar. Vamos criar dois procedimentos muito simples:
Agora vamos criar um wrapper que os execute várias vezes, com e sem o prefixo do esquema:
Resultados:
Conclusões:
A questão mais importante: por que você deseja usar o prefixo sp_? O que seus colegas esperam ganhar com isso? Isso não deve significar que você precisa provar que isso é pior, mas justificar a adição do mesmo prefixo de três letras a cada procedimento armazenado no sistema. Não vejo o benefício.
Também realizei alguns testes bastante extensos desse padrão na seguinte postagem no blog:
http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix
fonte
sp_
para que eles pudessem ser diferenciados de outras coisas e sem conflitos de nomes ... Eu não tinha ideia de que esse problema de desempenho existia.Como mostra o comentário simples de Martin Smith - sim, se você tiver um procedimento armazenado com um
sp_
prefixo - o executor de consultas do SQL Server sempre fará check-in nomaster
banco de dados primeiro para ver se existe um procedimento armazenado (marcado como um procedimento armazenado no sistema) com esse nome.E, se existir, o procedimento armazenado no sistema do
master
banco de dados sempre prevalecerá e será executado em vez do seu.Então sim - ele ainda permanece: não use o
sp_
prefixo.fonte
CREATE PROC dbo.sp_helptext AS SELECT 1
então tente #EXEC dbo.sp_helptext
master
sp's.Um teste melhor é escrever uma consulta que exija otimização total, pois provavelmente é um reflexo melhor do que o processo que você está escrevendo está fazendo. Embrulhei a consulta a seguir em um SP e repeti seu teste e obtive os mesmos resultados.
Recebi o mesmo número de eventos de falta e acerto de cache nos dois casos e, nos dois casos, o plano foi adicionado ao cache. Também executei os dois procs várias vezes e não houve diferença consistente no tempo da CPU ou no tempo decorrido relatado pelo dm_exec_query_stats.
A outra preocupação é que, como "sp_" procs podem ser executados a partir do master, você pode obter uma cópia do proc executada no master em vez do DB em que está trabalhando, mas um teste rápido mostrará que não é esse o caso. No entanto, se o proc for retirado do banco de dados em que você está trabalhando e uma cópia existir no master, ela será executada, o que pode ser um problema se for uma versão antiga. Se isso é uma preocupação, eu não usaria "sp_" para nomear o proc.
fonte
Acredito que o problema tenha que ser resolvido quando você não especificar o nome completo do objeto. Portanto, "EXEC sp_something" verificará o mestre primeiro, mas "EXEC dbname.dbo.sp_something" nunca irá dominar primeiro.
A lição, se bem me lembro, é sempre usar o nome completo.
fonte
EXEC MyDB.dbo.sp_helptext 'sp_helptext'
ainda usa omaster
mesmo, se houver um no banco de dados do usuário. AFAIK verifica os dois locais e usará o localmaster
se existir e estiver marcado como um objeto do sistema.MyDB.dbo.sp_foo
ainda executei a versão mestre). Não tenho o R2 2008/2008 no momento para confirmar onde esse comportamento foi alterado.