Stiamo riscontrando un'enorme differenza tra queste query.SQL perché SELECT COUNT (*), MIN (col), MAX (col) più veloce di SELECT MIN (col), MAX (col)
La query lente
SELECT MIN(col) AS Firstdate, MAX(col) AS Lastdate
FROM table WHERE status = 'OK' AND fk = 4193
Tabella 'tabella'. Numero di scansioni 2, letture logiche 2458969, letture fisiche 0, letture read-ahead 0, letture logiche lob 0, letture fisiche lob 0, letture lob read-ahead 0.
Tempi di esecuzione SQL Server: Tempo CPU = 1966 ms , tempo trascorso = 1955 ms.
La query veloce
SELECT count(*), MIN(col) AS Firstdate, MAX(col) AS Lastdate
FROM table WHERE status = 'OK' AND fk = 4193
Tabella 'tabella'. Conteggio scansioni 1, letture logiche 5, letture logiche 0 lob, letture fisiche lob 0, letture lob read-ahead 0.
Tempi di esecuzione SQL Server: Tempo CPU = 0 ms , tempo trascorso = 9 ms.
Domanda
Qual è la ragione tra l'enorme differenza di prestazioni tra le query?
Aggiornamento Un piccolo aggiornamento sulla base di questioni indicate come commenti:
L'ordine di esecuzione o di esecuzione ripetuta cambia nulla prestazioni saggio. Non ci sono parametri aggiuntivi usati e il database (test) non sta facendo altro durante l'esecuzione.
query lente
|--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)
veloce interrogazione
|--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)
risposta
La risposta data dal di sotto Martin Smith sembra spiegare il problema. La versione super short è che l'analizzatore di query MS-SQL utilizza erroneamente un piano di query nella query lenta che causa una scansione completa della tabella.
Aggiunta di un conteggio (*), il suggerimento di query con (FORCESCAN) o un indice combinato alla data di inizio, FK e colonne di stato corregge il problema di prestazioni.
cosa succede se si esegue nuovamente la prima query dopo la seconda query? – gbn
Forse perché quando si utilizza un conteggio (*) non si controlla ogni record per fk = 4193? – nosbor
Stai correndo uno dopo l'altro? In tal caso: cosa succede se metti 'DBCC DROPCLEANBUFFERS' e' DBCC FREEPROCCACHE' prima di entrambe le query? Cosa succede se cambi la sequenza: esegui prima la query veloce, poi quella lenta? –