Estamos viendo una gran diferencia entre estas consultas.SQL por qué es SELECT COUNT (*), MIN (col), MAX (col) más rápido que SELECT MIN (col), MAX (col)
La consulta lenta
SELECT MIN(col) AS Firstdate, MAX(col) AS Lastdate
FROM table WHERE status = 'OK' AND fk = 4193
Tabla 'mesa'. Número de escaneo 2, lecturas lógicas 2458969, lecturas físicas 0, lecturas anticipadas 0, lecturas lógicas lob 0, lecturas físicas lob 0, lecturas lecturas lob 0.
Tiempos de ejecución del servidor SQL: Tiempo de CPU = 1966 ms , tiempo transcurrido = 1955 ms.
La consulta rápida
SELECT count(*), MIN(col) AS Firstdate, MAX(col) AS Lastdate
FROM table WHERE status = 'OK' AND fk = 4193
Tabla 'mesa'. Número de exploraciones 1, lógica lee 5803, lecturas físicas 0, la lectura anticipada lee 0, vaselina lecturas lógicas 0, física lee 0 vaselina, vaselina lectura anticipada es 0.
servidor de ejecución de SQL tiempos: CPU = 0 ms , tiempo transcurrido = 9 ms.
Pregunta
Cuál es la razón entre la gran diferencia de rendimiento entre las consultas?
actualización Una pequeña actualización basada en preguntas dadas como comentarios:
El orden de ejecución o ejecución repetida cambia nada el rendimiento sabia. No se usan parámetros adicionales y la base de datos (prueba) no está haciendo nada más durante la ejecución.
consulta lenta
|--Nested Loops(Inner Join)
|--Stream Aggregate(DEFINE:([Expr1003]=MIN([DBTest].[dbo].[table].[startdate])))
| |--Top(TOP EXPRESSION:((1)))
| |--Nested Loops(Inner Join, OUTER REFERENCES:([DBTest].[dbo].[table].[id], [Expr1008]) WITH ORDERED PREFETCH)
| |--Index Scan(OBJECT:([DBTest].[dbo].[table].[startdate]), ORDERED FORWARD)
| |--Clustered Index Seek(OBJECT:([DBTest].[dbo].[table].[PK_table]), SEEK:([DBTest].[dbo].[table].[id]=[DBTest].[dbo].[table].[id]), WHERE:([DBTest].[dbo].[table].[FK]=(5806) AND [DBTest].[dbo].[table].[status]<>'A') LOOKUP ORDERED FORWARD)
|--Stream Aggregate(DEFINE:([Expr1004]=MAX([DBTest].[dbo].[table].[startdate])))
|--Top(TOP EXPRESSION:((1)))
|--Nested Loops(Inner Join, OUTER REFERENCES:([DBTest].[dbo].[table].[id], [Expr1009]) WITH ORDERED PREFETCH)
|--Index Scan(OBJECT:([DBTest].[dbo].[table].[startdate]), ORDERED BACKWARD)
|--Clustered Index Seek(OBJECT:([DBTest].[dbo].[table].[PK_table]), SEEK:([DBTest].[dbo].[table].[id]=[DBTest].[dbo].[table].[id]), WHERE:([DBTest].[dbo].[table].[FK]=(5806) AND [DBTest].[dbo].[table].[status]<>'A') LOOKUP ORDERED FORWARD)
consulta rápida
|--Compute Scalar(DEFINE:([Expr1003]=CONVERT_IMPLICIT(int,[Expr1012],0)))
|--Stream Aggregate(DEFINE:([Expr1012]=Count(*), [Expr1004]=MIN([DBTest].[dbo].[table].[startdate]), [Expr1005]=MAX([DBTest].[dbo].[table].[startdate])))
|--Nested Loops(Inner Join, OUTER REFERENCES:([DBTest].[dbo].[table].[id], [Expr1011]) WITH UNORDERED PREFETCH)
|--Index Seek(OBJECT:([DBTest].[dbo].[table].[FK]), SEEK:([DBTest].[dbo].[table].[FK]=(5806)) ORDERED FORWARD)
|--Clustered Index Seek(OBJECT:([DBTest].[dbo].[table].[PK_table]), SEEK:([DBTest].[dbo].[table].[id]=[DBTest].[dbo].[table].[id]), WHERE:([DBTest].[dbo].[table].[status]<'A' OR [DBTest].[dbo].[table].[status]>'A') LOOKUP ORDERED FORWARD)
respuesta
La respuesta dada por debajo Martin Smith parece explicar el problema. La versión súper corta es que el analizador de consultas MS-SQL usa erróneamente un plan de consulta en la consulta lenta, lo que causa un escaneo completo de la tabla.
Al agregar un recuento (*), la sugerencia de consulta con (FORCESCAN) o un índice combinado en la fecha de inicio, FK y las columnas de estado corrige el problema de rendimiento.
¿Qué sucede si ejecuta la primera consulta después de la segunda consulta nuevamente? – gbn
¿Quizás porque cuando estás usando un conteo (*) no revisas todos los registros de fk = 4193? – nosbor
¿Estás ejecutando estos uno tras otro? Si es así: ¿qué sucede si coloca 'DBCC DROPCLEANBUFFERS' y' DBCC FREEPROCCACHE' antes de ambas consultas? ¿Qué sucede si cambias la secuencia? ¿Ejecutas primero la consulta rápida y luego la lenta? –