Uno de mis compañeros de trabajo nombró un procedimiento almacenado en nuestra base de datos SQL Server 2008 R2 sp_something
. Cuando vi esto, inmediatamente pensé: "¡Eso está MAL!" y comencé a buscar en mis marcadores este artículo en línea que explica por qué está mal, para que yo pueda darle una explicación a mi compañero de trabajo.
En el artículo (por Brian Moran ) se explica que al dar al procedimiento almacenado un prefijo sp_, SQL Server busca en la base de datos maestra un plan compilado. Debido a que el sp_sproc
no reside allí, SQL Server volverá a compilar el procedimiento (y necesita un bloqueo de compilación exclusivo para eso, causando problemas de rendimiento).
El siguiente ejemplo se da en el artículo para mostrar la diferencia entre dos procedimientos:
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
Ejecuta esto, luego abre Profiler (agrega los procedimientos almacenados -> SP:CacheMiss
evento) y ejecuta los procedimientos almacenados nuevamente. Se supone que ve una diferencia entre los dos procedimientos almacenados: el sp_Select1
procedimiento almacenado generará un SP:CacheMiss
evento más que el Select1
procedimiento almacenado (el artículo hace referencia a SQL Server 7.0 y SQL Server 2000 ).
Cuando ejecuto el ejemplo en mi entorno SQL Server 2008 R2, obtengo la misma cantidad de SP:CacheMiss
eventos para ambos procedimientos (tanto en tempdb como en otra base de datos de prueba).
Entonces me pregunto:
- ¿Puedo haber hecho algo mal en mi ejecución del ejemplo?
¿sproc sp_something
Sigue siendo válido el adagio " no nombrar a un usuario " en las versiones más recientes de SQL Server?- Si es así, ¿hay algún buen ejemplo que muestre su validez en SQL Server 2008 R2?
Muchas gracias por tus pensamientos sobre esto!
EDITAR
Encontré la creación de procedimientos almacenados (motor de base de datos) en msdn para SQL Server 2008 R2, que responde a mi segunda pregunta:
Recomendamos que no cree ningún procedimiento almacenado utilizando sp_ como prefijo. SQL Server usa el prefijo sp_ para designar procedimientos almacenados del sistema. El nombre que elija puede entrar en conflicto con algún procedimiento futuro del sistema. [...]
Sin embargo, no se menciona nada sobre los problemas de rendimiento causados por el uso del sp_
prefijo. Me encantaría saber si ese es el caso o si lo arreglaron después de SQL Server 2000.
sp_
versiones (es necesario verificar en las bases de datos maestra y de usuario porque prioriza los procesos del sistema enmaster
-> procesos en la base de datos de usuario -> no sistema procs inmaster
)sp_
? Esto es tan útil como prefijar una tabla contbl
. ¿Por qué primero hacer que el sistema busque maestro (incluso si es insignificante o no tiene una diferencia de rendimiento) para permitirle usar esta convención de nomenclatura sin sentido?dbo.sp_Author_Rename
es mejor quedbo.Author_Rename
. No puedo pensar en una sola cosa que tenga sentido.Respuestas:
Esto es bastante fácil de probarse a sí mismo. Vamos a crear dos procedimientos muy simples:
Ahora construyamos un contenedor que los ejecute varias veces, con y sin el prefijo de esquema:
Resultados:
Conclusiones:
La pregunta más importante: ¿por qué se quiere utilizar el prefijo sp_? Lo que a sus compañeros de trabajo esperan obtener de este modo? Esto no debería ser acerca de usted tener que probar que esto es peor, debe ser por ellos justificar la adición de la misma prefijo de tres letras para cada procedimiento almacenado única en el sistema. No veo el beneficio.
También he realizado algunos bastante extensas pruebas de este patrón en la siguiente entrada en el blog:
http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix
fuente
sp_
para que pudieran diferenciarse de otras cosas y no tener conflictos de nombres ... No tenía idea de que este problema de rendimiento existiera.Como muestra el simple comentario de Martin Smith, sí, si tiene un procedimiento almacenado con un
sp_
prefijo, el ejecutor de consultas de SQL Server siempre verificarámaster
primero la base de datos para ver si existe un procedimiento almacenado (marcado como un procedimiento almacenado del sistema) con ese nombre.Y si existe, ese procedimiento almacenado del sistema de la
master
base de datos siempre prevalece y se ejecutará en lugar del suyo.Entonces sí, sigue en pie: no use el
sp_
prefijo.fuente
CREATE PROC dbo.sp_helptext AS SELECT 1
luego intenteEXEC dbo.sp_helptext
master
sp.Una mejor prueba es escribir una consulta que requiera una optimización completa, ya que probablemente sea un mejor reflejo de lo que está haciendo el proceso que está escribiendo. Envuelto la siguiente consulta en un SP y repetí su prueba y obtuve los mismos resultados.
Obtuve la misma cantidad de eventos de aciertos y errores de caché en ambos casos y en ambos casos el plan se agregó al caché. También ejecuté ambos procesos varias veces y no hubo diferencias consistentes en el tiempo de CPU o el tiempo transcurrido informado por dm_exec_query_stats.
La otra preocupación es que, dado que los procesos "sp_" se pueden ejecutar desde el maestro, puede obtener una copia del proceso que se ejecutó en el maestro en lugar del DB en el que está trabajando, pero una prueba rápida mostrará que ese no es el caso. Sin embargo, si el proceso se elimina del DB en el que está trabajando y existe una copia en el maestro, se ejecutará, lo que podría ser un problema si se trata de una versión anterior. Si esto es un problema, no usaría "sp_" para nombrar el proceso
fuente
Creo que el problema tiene que ver cuando no especifica el nombre completo del objeto. Por lo tanto, "EXEC sp_something" verificará el maestro primero, pero "EXEC dbname.dbo.sp_something" nunca irá al maestro primero.
La lección, si mal no recuerdo, es usar siempre el nombre completo.
fuente
EXEC MyDB.dbo.sp_helptext 'sp_helptext'
todavía usa el demaster
incluso si hay uno en la base de datos del usuario. AFAIK verifica ambas ubicaciones y usará la demaster
si existe y está marcada como un objeto del sistema.MyDB.dbo.sp_foo
aún ejecuté la versión maestra). No tengo 2008/2008 R2 en este momento para confirmar dónde cambió este comportamiento.