Una mirada inicial a los planes de ejecución muestra que la expresión 1/0
se define en los operadores de Calcular Escalar:
Ahora, a pesar de que los planes de ejecución comienzan a ejecutarse en el extremo izquierdo, invocando iterativamente Open
y GetRow
métodos en iteradores secundarios para devolver resultados, SQL Server 2005 y posterior contiene una optimización mediante la cual las expresiones a menudo solo son definidas por un Escalar de cómputo, con evaluación diferida hasta un posterior La operación requiere el resultado :
En este caso, el resultado de la expresión solo es necesario cuando se ensambla la fila para regresar al cliente (lo que se puede pensar que ocurre en el SELECT
ícono verde ). Según esa lógica, la evaluación diferida significaría que la expresión nunca se evalúa porque ninguno de los planes genera una fila de retorno. Para trabajar un poco el punto, ni el Clustered Index Seek ni el Table Scan devuelven una fila, por lo que no hay una fila para ensamblar y devolver al cliente.
Sin embargo, hay una optimización separada por la cual algunas expresiones pueden identificarse como constantes de tiempo de ejecución y evaluarse una vez antes de que comience la ejecución de la consulta . En este caso, se puede encontrar una indicación de esto en el XML del plan de presentación (plan de búsqueda de índice agrupado a la izquierda, plan de escaneo de tabla a la derecha):
Escribí más sobre los mecanismos subyacentes y cómo pueden afectar el rendimiento en esta publicación de blog . Usando la información proporcionada allí, podemos modificar la primera consulta para que ambas expresiones se evalúen y se almacenen en caché antes de que comience la ejecución:
select 1/0 * CONVERT(integer, @@DBTS)
from #temp
where id = 1
select 1/0
from #temp2
where id = 1
Ahora, el primer plan también contiene una referencia de expresión constante, y ambas consultas producen el mensaje de error. El XML para la primera consulta contiene:
Más información: Calcular escalares, expresiones y rendimiento