¿Usar IF en T-SQL debilita o rompe el almacenamiento en caché del plan de ejecución?

20

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á?

AnthonyWJones
fuente
1
SQL Server puede y reutiliza el plan de ejecución ya que no considera las ramas, solo las declaraciones contenidas en las ramas.
MartinC

Respuestas:

10

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.

MartinC
fuente
6

El único atajo será IF 1 = 1

Tanto @parameter como EXISTS aún requieren procesamiento para el "caso general" ( @parameter = 42digamos)

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)

gbn
fuente
3

Intente mostrar el plan de ejecución estimado, no el real. Verá que el primero contiene CONDoperador.

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.

Tom V - Equipo Mónica
fuente
0

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.

Barry King
fuente
0

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
2
2005+ tiene una recompilación de nivel de estado por lo que ya no tiene "un plan por sp" todo el tiempo
gbn