(Pregunta movida de SO)
Tengo una tabla (datos ficticios) con índice agrupado que contiene 2 columnas:
Ahora ejecuto esas dos consultas:
declare
@productid int =1 ,
@priceid int = 1
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid OR @productid IS NULL)
AND (priceid = @priceid OR @priceid IS NULL)
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid)
AND (priceid = @priceid)
El plan de ejecución real para ambas consultas es:
Como puede ver, el primero usa SCAN mientras que el segundo usa SEEK.
Sin embargo, agregando OPTION (RECOMPILE)
a la primera consulta, hizo el plan de ejecución también para usar SEEK:
Amigos en el chat de DBA me dijeron que:
En su consulta, @ productid = 1, lo que significa que (productID = @ productID OR @productID IS NULL) puede simplificarse a (productID = @ productID). El primero requiere un escaneo para funcionar con cualquier valor de @productID, el último podría usar una búsqueda. Entonces, cuando usa RECOMPILE, SQL Server analizará qué valor tiene realmente en @productID y hará el mejor plan para ello. Con un valor no nulo en @productID, una búsqueda es lo mejor. Si se desconoce el valor de @productID, el plan debe adaptarse a cualquier valor posible en @productID, lo que requeriría un escaneo. Tenga cuidado: OPTION (RECOMPILE) forzará una recompilación del plan cada vez que lo ejecute, lo que agregará unos pocos milisegundos a cada ejecución. Aunque esto solo es un problema si la consulta se ejecuta con mucha frecuencia.
También :
Si @productID es nulo, ¿qué valor buscarías? Respuesta: no hay nada que buscar. Todos los valores califican.
Entiendo que OPTION (RECOMPILE)
obliga a SQL Server a ver qué valores reales tienen los parámetros y ver si puede BUSCAR con ellos.
Pero ahora pierdo el beneficio de la compilación anticipada.
Pregunta
En mi humilde opinión, SCAN solo ocurrirá si un parámetro es nulo.
Está bien: deje que SQL SERVER cree un plan de ejecución para SCAN.
PERO si SQL Server ve que ejecuto esta consulta muchas veces con valores: 1,1
entonces, ¿por qué no crea OTRO plan de ejecución y usa SEEK para eso?
AFAIK - SQL crea un plan de ejecución para las consultas más exitosas .
¿Por qué SQL SERVER no guarda un plan de ejecución para:
@productid int =1 , @priceid int = 1
(Lo ejecuto muchas veces con esos valores)
- ¿Es posible forzar a SQL a mantener ese plan de ejecución (que usa SEEK) para futuras invocaciones?