Estoy tratando de entender un problema que tenemos con SQL Server 2000. Somos un sitio web moderadamente transaccional y tenemos un proceso almacenado llamado sp_GetCurrentTransactions
que acepta un ID de cliente y dos fechas.
Ahora, según las fechas y el cliente, esta consulta puede devolver cualquier cosa, desde cero hasta miles de filas.
El problema: lo que hemos experimentado es que de repente obtendremos una serie de errores (típicamente Execution Timeout Expired
o similares) para un cliente en particular mientras intentan ejecutar ese proceso almacenado. Así que examinamos la consulta, la ejecutamos en SSMS y descubrimos que tarda 30 segundos. Así que volvemos a compilar el proceso almacenado y -bang- ahora se ejecuta en 300 ms.
He hablado con nuestro DBA sobre esto. Me ha dicho que la base de datos creó un plan de consulta cuando creamos el proceso almacenado. Dijo que era un buen plan para ese conjunto de parámetros, pero si le arroja un cierto conjunto de parámetros, entonces el plan no será el mejor plan para esos datos, por lo que verá que se ejecuta lentamente.
Las opciones que se me presentan son mover esa consulta problemática desde un proceso almacenado y volver al SQL dinámico que tiene su plan de ejecución creado en cada ejecución.
Esto se siente como un paso atrás para mí y siento que debe haber una forma de evitar esto. ¿Hay alguna otra forma de lidiar con este problema?
Todas y cada una de las respuestas son apreciadas.
fuente
Respuestas:
Este problema se llama análisis de parámetros.
Las versiones posteriores de SQL Server le brindan más opciones para tratarlo, como
OPTION (RECOMPILE)
oOPTIMIZE FOR
sugerencias.Puede intentar declarar variables en el procedimiento almacenado, asignar los valores de los parámetros a las variables y usar las variables en lugar de los parámetros, ya que parece que la mayoría de las veces obtiene un plan razonablemente satisfactorio.
Normalmente, los planes más catastróficamente malos son aquellos compilados para parámetros con muy alta selectividad pero ejecutados con parámetros con baja selectividad.
Suponiendo que el plan generado es más robusto con este enfoque y satisfactorio para todos los valores de los parámetros, la ventaja de este enfoque sobre lo sugerido por JNK es que no incurre en un costo de compilación por cada llamada.
La desventaja es que, para algunas ejecuciones, el tiempo de ejecución podría ser mayor que para un plan diseñado específicamente para esos valores de parámetros, por lo que es una compensación del tiempo de compilación frente al tiempo de ejecución.
fuente
En lugar de utilizar SQL dinámico, siempre puede cambiar sus llamadas de proceso a:
EXEC Database.dbo.usp_Myprocedure 'Parameter' WITH RECOMPILE
Las
WITH RECOMPILE
fuerzas (¡lo adivinaste!) Una recompilación del plan de ejecución cada vez que se ejecuta.También puede incluir
WITH RECOMPILE
en la definición del proceso almacenado:fuente
También podría intentar decidir la base de datos que planea usar, aunque estaría luchando con el optimizador un poco, por lo que es más frágil de lo que esperaría.
La técnica es esta: divida el procedimiento almacenado en 2, uno destinado a un conjunto de parámetros, uno para otro. Agregue las cláusulas where a cada una de manera que entre ellas cubran todos los casos posibles. Mire los planes de consulta: uno debe estar optimizado para un conjunto de parámetros, el otro para el otro conjunto. Es posible que tenga que jugar con la consulta para que esto suceda, o esto puede no ser posible para su consulta, en cuyo caso este enfoque no funcionará.
Ahora haga que su procedimiento almacenado original verifique los valores de los parámetros y envíelo al uno de los dos procedimientos almacenados del párrafo anterior.
Esto puede funcionar, pero es una especie de truco para forzar al optimizador a trabajar de manera más efectiva para su consulta. Como todos estos hacks, en futuras versiones de la base de datos puede ser innecesario o incluso empeorar las cosas. Entonces, incluso si funciona, tienes que decidir si vale la pena.
fuente
También puede probar
SET FORCEPLAN
e indexar sugerencias.http://msdn.microsoft.com/en-us/library/ms188344.aspx
Básicamente le permite elegir en qué orden ocurre la unión.
Puede tener sugerencias de índice para asegurarse de que el servidor SQL utiliza los índices correctos.
fuente
Hmmm ... si nos centramos solo en este procedimiento almacenado, me sorprendería que el uso del plan de ejecución en caché podría causar el problema que está viendo. Solicitaría ver el plan de ejecución del procedimiento almacenado utilizando un conjunto de parámetros para el cliente y las dos fechas. Me pregunto si un índice más específico sería útil -> como en customerId, y solo en las dos fechas.
fuente
El rendimiento repentinamente degradante suena como un plan de consulta ineficiente que se produce, probablemente como resultado de estadísticas faltantes. Ejecute un generador de perfiles de SQL Server con las categorías de eventos "Errores y advertencias" establecidas y vea si hay advertencias sobre estadísticas faltantes.
También es posible que le falte un índice, o que necesite desfragmentar los índices, ya que pueden estar demasiado fragmentados para que SQL Server los use, lo que hace pensar que un Table Scan producirá menos E / S.
@JNK plantea un gran punto sobre los procesos almacenados: estos se compilan por adelantado y el plan de consulta se almacenará junto con el procedimiento almacenado.
No estoy necesariamente de acuerdo con el uso de WITH RECOMPILE, ya que luego pierde el beneficio de que el plan de consultas se almacene y reutilice. Hay algunos casos en que esto es necesario, es decir, si las estadísticas de distribución en las tablas subyacentes difieren mucho entre llamadas, pero generalmente, una vez que los datos en las tablas están maduros, la distribución de datos dentro de las tablas variará mínimamente.
Entonces, para resumir:
fuente