No intentaré explicar los detalles completos de la detección de parámetros, pero en resumen, no, no siempre ayuda (y puede entorpecer).
Imagine una tabla (T) con una clave principal y una columna de Fecha indexada (A), en la tabla hay 1000 filas, 400 tienen el mismo valor de A (digamos hoy 20130122), las 600 filas restantes son los próximos 600 días , por lo que solo 1 registro por fecha.
Esta consulta:
SELECT *
FROM T
WHERE A = '20130122';
Producirá un plan de ejecución diferente a:
SELECT *
FROM T
WHERE A = '20130123';
Dado que las estadísticas indicarán que se devolverán las primeras 400 de 1000 filas, el optimizador debe reconocer que una exploración de tabla será más eficiente que una búsqueda de marcador, mientras que la segunda solo generará 1 fila, por lo que una búsqueda de marcador será mucho más eficiente. más eficiente.
Ahora, volviendo a su pregunta, si hiciéramos de esto un procedimiento:
CREATE PROCEDURE dbo.GetFromT @Param DATE
AS
SELECT *
FROM T
WHERE A = @Param
Entonces corre
EXECUTE dbo.GetFromT '20130122'; --400 rows
Se usará el plan de consulta con el escaneo de la tabla, si la primera vez que lo ejecuta usa '20130123' como parámetro, almacenará el plan de búsqueda de marcadores. Hasta que se vuelva a compilar el procedimiento, el plan seguirá siendo el mismo. Haciendo algo como esto:
CREATE PROCEDURE dbo.GetFromT @Param VARCHAR(5)
AS
DECLARE @Param2 VARCHAR(5) = @Param;
SELECT *
FROM T
WHERE A = @Param2
Entonces esto se ejecuta:
EXECUTE dbo.GetFromT '20130122';
Si bien el procedimiento se compila de una sola vez, no fluye correctamente, por lo que el plan de consulta creado en la primera compilación no tiene idea de que @Param2 será igual a @param, por lo que el optimizador (sin saber cuántas filas esperar) asumirá que se devolverán 300 (30%), por lo que considerará que un escaneo de tabla es más eficiente que una búsqueda de marcador. Si ejecutó el mismo procedimiento con '20130123' como parámetro, generaría el mismo plan (independientemente del parámetro con el que se invocó por primera vez) porque las estadísticas no se pueden usar para un valor desconocido. Por lo tanto, ejecutar este procedimiento para '20130122' sería más eficiente, pero para todos los demás valores sería menos eficiente que sin parámetros locales (suponiendo que el procedimiento sin parámetros locales se invocó primero con algo que no sea '20130122')
Algunas consultas para demostrar para que pueda ver los planes de ejecución por sí mismo
Crear esquema y datos de muestra
CREATE TABLE T (ID INT IDENTITY(1, 1) PRIMARY KEY, A DATE NOT NULL, B INT,C INT, D INT, E INT);
CREATE NONCLUSTERED INDEX IX_T ON T (A);
INSERT T (A, B, C, D, E)
SELECT TOP 400 CAST('20130122' AS DATE), number, 2, 3, 4
FROM Master..spt_values
WHERE type = 'P'
UNION ALL
SELECT TOP 600 DATEADD(DAY, number, CAST('20130122' AS DATE)), number, 2, 3, 4
FROM Master..spt_values
WHERE Type = 'P';
GO
CREATE PROCEDURE dbo.GetFromT @Param DATE
AS
SELECT *
FROM T
WHERE A = @Param
GO
CREATE PROCEDURE dbo.GetFromT2 @Param DATE
AS
DECLARE @Param2 DATE = @Param;
SELECT *
FROM T
WHERE A = @Param2
GO
Ejecutar procedimientos (mostrando el plan de ejecución real):
EXECUTE GetFromT '20130122';
EXECUTE GetFromT '20130123';
EXECUTE GetFromT2 '20130122';
EXECUTE GetFromT2 '20130123';
GO
EXECUTE SP_RECOMPILE GetFromT;
EXECUTE SP_RECOMPILE GetFromT2;
GO
EXECUTE GetFromT '20130123';
EXECUTE GetFromT '20130122';
EXECUTE GetFromT2 '20130123';
EXECUTE GetFromT2 '20130122';
Verás que la primera vez GetFromT
se compila, usa un escaneo de tabla y lo retiene cuando se ejecuta con el parámetro '20130122', GetFromT2
también usa un escaneo de tabla y retiene el plan para '20130122'.
Después de que los procedimientos se hayan configurado para la recompilación y se vuelvan a ejecutar (observe en un orden diferente), GetFromT
usa un bucle de marcador y retiene el plan para '20130122', a pesar de haber considerado previamente que un escaneo de tabla es un plan más apropiado. GetFromT2
no se ve afectado por la orden y tiene el mismo plan que antes de la recompilación.
Entonces, en resumen, depende de la distribución de sus datos y sus índices, su frecuencia de recompilación y un poco de suerte si un procedimiento se beneficiará del uso de variables locales. Ciertamente no siempre ayuda.
Espero haber arrojado algo de luz sobre el efecto del uso de parámetros locales, planes de ejecución y compilación de procedimientos almacenados. Si he fallado por completo o me he perdido un punto clave, puede encontrar una explicación mucho más detallada aquí:
http://www.sommarskog.se/query-plan-mysteries.html