Tengo una declaración de eliminación que utiliza un plan incorrecto cuando se ejecuta dentro de un procedimiento almacenado, pero está eligiendo un plan mucho mejor cuando se ejecuta ad-hoc.
Reconstruí todos los índices de las tablas utilizadas por la consulta y eliminé todas las memorias caché. El optimizador aún elige el plan incorrecto para el procedimiento almacenado.
Me gustaría saber por qué el optimizador está utilizando un plan de ejecución diferente para el procedimiento almacenado en comparación con el SQL ad-hoc.
ACTUALIZACIÓN: supongo que deben haber sido los parámetros después de todo, cuando ejecuté el código ad-hoc con la variable codificada, puedo obtener el plan "incorrecto" con el valor correcto (es una fecha, valores que tienen un año de antigüedad parece generar el "buen" plan). Ahora trata de forzar el plan "bueno" en el proceso utilizando una sugerencia de consulta.
SOLUCIÓN: Terminé obteniendo el plan que quería usando la sugerencia OPTIMIZAR PARA DESCONOCIDO.
fuente
WHERE
cláusula?Respuestas:
Sospechosos de siempre:
Punto 1: el optimizador puede elegir el mejor plan para las constantes.
Cambiar las constantes = cambiar el plan. Un plen parametrizado es valioso
El punto 2 introducirá conversiones implícitas debido a la precedencia del tipo de datos,
por ejemplo, columna varchar en comparación con el parámetro nvarchar
Punto 3: use el enmascaramiento de parámetros u OPTIMIZAR PARA DESCONOCIDO
Editar: Para probar: ejecute el proceso almacenado, ejecute sp_updatestats, vuelva a ejecutar. Esto invalidará los planes almacenados en caché, lo que es mejor que borrar el caché del plan
Editar: después del comentario de jcolebrand
Puede deshabilitar el rastreo de varias maneras. Los 3 principales son
Parámetro de enmascaramiento:
El enmascaramiento y la sugerencia OPTIMIZE tienen el mismo efecto (tal vez por diferentes razones). Es decir, el optimizador tiene que usar estadísticas y distribución de datos ( Nota: todavía bajo prueba por Mark Storey-Smith )
evaluar los parámetros en sus propios méritos ?, en lugar de lo que fueron la última llamada. El optimizador puede recompilar o no. SQL Server 2005 agregó una recompilación de nivel de declaración para que haya menos impactoAhora, por qué un plan con parámetros "olfateados" es "rígido" en comparación con parámetros enmascarados / "desconocidos", no estoy seguro.
He usado el enmascaramiento de parámetros desde SQL Server 2000 para todo menos el código más simple. He notado que es probable que suceda con un código más complejo. Y en mi antiguo trabajo tengo algunos informes de informes que podrían cambiar los valores predeterminados de los parámetros del plan. Creo que el enfoque de "culto a la carga" fue más fácil que una llamada de soporte.
Edición 2, 12 de octubre de 2011, después de un chat
El enmascaramiento de parámetros y OPTIMIZAR PARA DESCONOCIDO tienen el mismo efecto por lo que puedo decir.
La sugerencia es más limpia que el enmascaramiento, pero se agregó con SQL Server 2008.
El rastreo de parámetros ocurre en tiempo de compilación.
WITH RECOMPILE genera un nuevo plan cada ejecución. Esto significa que una mala elección de los valores predeterminados influirá en el plan. En mi último trabajo, pude demostrarlo fácilmente con un código de informe: cambiar los valores predeterminados de los parámetros alteró el plan independientemente de los parámetros suministrados.
Este artículo de MS Connect es interesante: uso de índice subóptimo dentro del procedimiento almacenado (mencionado en una de las respuestas SO a continuación)
Cuestiones pendientes
¿Todavía se aplica el olfateo con WITH RECOMPILE? Es decir, si el optimizador sabe descartar el plan, ¿tiene como objetivo la reutilización?
¿Por qué los planes olfateados son "pegajosos"?
Enlaces de SO:
https://stackoverflow.com/q/272726/27535
Remus Rusanu (equipo de MS SQL) y yo tuvimos una pelea aquí en SO
fuente
OPTION (RECOMPILE)
o todo el procesoWITH RECOMPILE
para obligar a SQL Server a ignorar los planes existentes.OPTIMIZE
, porque Microsoft es una empresa estadounidense. :)No olvide que la configuración ANSI que ha configurado para el plan de conexión desempeña un papel en la selección del plan de ejecución. Cuando la aplicación llama al procedimiento almacenado, probablemente tenga una configuración ANSI diferente a la de su conexión SSMS.
fuente