2011-12-05 9 views
5

Esta pregunta no se trata tanto de encontrar una solución como de obtener una explicación para el comportamiento bizarrest que he visto desde SQL Server.Rendimiento del procedimiento almacenado: ¿esto es SALVAJE?

I tenían un procedimiento almacenado con la firma siguiente:

alter procedure MySP @param1 uniqueidentifier, 
        @param2 uniqueidentifier, 
        @param3 uniqueidentifier 

Dado un cierto conjunto de parámetros, este proc estaba tomando un tiempo muy largo para funcionar de C# (usando SqlCommand.ExecuteReader()) - aproximadamente 2 minutos. Usando los mismos parámetros en una sesión de consulta directa, el SP se ejecutó en menos de 2 segundos.

que tomó mucho tiempo, y ni siquiera a intentar explicar cómo nos topamos con esta solución, pero esto es lo que hicimos:

Al comienzo de la SP, que declaró el 3 de variables locales y ellas asignada a los valores de los parámetros, así:

declare @param1_copy uniqueidentifier, 
     @param2_copy uniqueidentifier, 
     @param3_copy uniqueidentifier 

select @param1_copy = @param1, 
     @param2_copy = @param2, 
     @param3_copy = @param3 

Y luego, en el resto de la SP sustituimos todas las referencias a los parámetros de entrada con las copias locales.

Voila. SP ejecutado en menos de 2 segundos. Y el equipo aquí está desconcertado.

Ahora, señoras y señores, ¿alguien puede explicar este comportamiento?

Respuesta

8

Esto suena como parameter sniffing.

de la definición de Microsoft:

"descubrimiento de parámetros" se refiere a un proceso por el entorno de ejecución de SQL Server "olfatea" los valores actuales de los parámetros durante la compilación o recompilación, y lo pasa junto al optimizador de consultas a fin de que se puede usar para generar planes de ejecución de consultas potencialmente más rápidos. La palabra "actual" se refiere a los valores de los parámetros presentes en la llamada de declaración que causó una compilación o una recompilación.

Parece que ya ha descubierto una solución, otra sería utilizar EXEC ... WITH RECOMPILE:

Cuando se ejecuta un procedimiento almacenado con valores de parámetros atípicos, "EXEC ... WITH RECOMPILE "se puede usar para garantizar que el plan de consulta nuevo no reemplace un plan en caché existente que se compiló utilizando valores de parámetros típicos.

+1

Increíble. ¡Nos dimos cuenta de la solución de libros de texto sin darnos cuenta! –

3

Sugiero leer el excelente artículo de Erland Sommarskog: Slow in the Application, Fast in SSMS? Understanding Performance Mysteries.

Tiene todos los detalles sobre este tema.

En general, cuando un plan de consulta se almacena en caché, algunas de las configuraciones de consulta se utilizan en la clave de caché. Estas configuraciones son diferentes en la configuración de SSMS predeterminada que en una cadena de conexión predeterminada, por lo que pueden existir diferentes planes de consulta.

+0

Probablemente sea mejor utilizar una palabra diferente que 'parámetro' aquí para evitar confusiones con los parámetros del procedimiento almacenado. –

+0

@MartinSmith - punto justo. Cambiado a 'configuración' - ¿qué piensas? – Oded

+0

me parece bien. El DMO estos se pueden encontrar en 'sys.dm_exec_plan_attributes' –

0

Tuve una situación similar cuando tenía un parámetro de tipo xml y me tomaba mucho tiempo ejecutarlo.Hice el mismo acercamiento y creé una variable local y pasé el valor del parámetro y funcionó súper rápido :)

Cuando SQL comienza a compilar el SP para crear su plan de ejecución, toma en cuenta los valores pasados ​​en sus parámetros para influir en el plan de ejecución. Pero si asigna los valores de los parámetros a una variable local y utiliza esa variable en su código SP, entonces el SQL no tendrá en cuenta los parámetros para influir en el plan de ejecución, por lo tanto, obtendrá una respuesta más rápida de la consulta.

Cuestiones relacionadas