Me han sugerido que el uso de sentencias IF en lotes t-SQL es perjudicial para el rendimiento. Estoy tratando de encontrar alguna confirmación o validar esta afirmación. Estoy usando SQL Server 2005 y 2008.
La afirmación es que con el siguiente lote: -
IF @parameter = 0
BEGIN
SELECT ... something
END
ELSE
BEGIN
SELECT ... something else
END
SQL Server no puede reutilizar el plan de ejecución generado porque la próxima ejecución puede necesitar una rama diferente. Esto implica que SQL Server eliminará una rama por completo del plan de ejecución sobre la base de que para la ejecución actual ya puede determinar qué rama se necesita. ¿Es esto realmente cierto?
Además de lo que sucede en este caso: -
IF EXISTS (SELECT ....)
BEGIN
SELECT ... something
END
ELSE
BEGIN
SELECT ... something else
END
donde no es posible determinar de antemano qué rama se ejecutará?
sql-server
sql-server-2008
sql-server-2005
query-performance
AnthonyWJones
fuente
fuente
Respuestas:
SQL Server optimiza el proceso de compilación del plan de consulta para el procedimiento almacenado al ignorar las ramas condicionales dentro del procedimiento almacenado. El plan se generará en función de los parámetros utilizados para la primera ejecución, esto causará problemas si los parámetros son diferentes para las ramas.
Colocaría el SQL para cada una de las ramas en su propio procedimiento almacenado, de modo que el plan generado se base en el uso real de los parámetros para esa rama.
fuente
El único atajo será
IF 1 = 1
Tanto @parameter como EXISTS aún requieren procesamiento para el "caso general" (
@parameter = 42
digamos)Dicho esto ... ¿qué dice el plan de ejecución real así como el generador de perfiles que captura los eventos de recompilación? (No me gustan los planes estimados según la respuesta de Jao)
fuente
Intente mostrar el plan de ejecución estimado, no el real. Verá que el primero contiene
COND
operador.Este operador también se incluyó en el plan de ejecución en caché. En su ejemplo, el plan de excitación estimado contendrá un operador COND y 2 ramas SELECT y, por lo tanto, será completamente reutilizable. Porque al ejecutar un lote, SQL Server evalúa no solo las declaraciones DML sino también todas las demás, obteniéndolas del plan.
El plan de ejecución interna es una estructura similar al árbol de expresiones.
fuente
Los planes se crearán en función de los parámetros pasados, por lo que en realidad diría que no, tener una lógica condicional que normalmente se basa en parámetros no es perjudicial para el rendimiento.
Obtendrá múltiples planes producidos, suponiendo que los parámetros causen una variación suficiente para que el optimizador de consultas lo note.
Puede ver qué activando el plan Show Execution y ejecutando los scripts, observe las diferencias en el plan. Cuando ejecute los procedimientos (supongo que los procedimientos almacenados aquí), notará que la primera vez es generalmente más rápida, el segundo golpe utiliza el plan almacenado. Cambie los parámetros y repita, luego ejecute los parámetros originales: en teoría, el plan todavía estará en la memoria caché, pero depende del uso del servidor (marcas de caché, no se quedan para siempre ...), etc.
fuente
Tal vez se haya mejorado en 2005 y 2008, pero el uso de condicionales en 2000 probablemente sea peor de lo que describe, compilaría un plan para manejar mejor la primera ejecución del procedimiento y luego usaría ese plan para ejecutar el procedimiento incluso cuando las condiciones cambiado En mi experiencia, esto provocó consultas que se ejecutaron en minutos para ejecutarse en horas. Aunque uso 2008 ahora y he usado 2005, no puedo comentar cómo funcionan los coditionales allí ya que ya no los uso.
fuente