Sono solo curioso di sapere perché una query aggregata viene eseguita molto più velocemente con una GROUP BY
clausola che senza una.
Ad esempio, l'esecuzione di questa query richiede quasi 10 secondi
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
Mentre questo richiede meno di un secondo
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
GROUP BY CreatedDate
Ne esiste solo uno CreatedDate
in questo caso, quindi la query raggruppata restituisce gli stessi risultati di quella non raggruppata.
Ho notato che i piani di esecuzione per le due query sono diversi: la seconda query utilizza il parallelismo mentre la prima query no.
È normale che SQL Server valuti diversamente una query aggregata se non ha una clausola GROUP BY? E c'è qualcosa che posso fare per migliorare le prestazioni della prima query senza usare una GROUP BY
clausola?
modificare
Ho appena imparato che posso usare OPTION(querytraceon 8649)
per impostare il costo in termini di costi del parallelismo su 0, il che fa sì che la query utilizzi un po 'di parallelismo e riduce il tempo di esecuzione a 2 secondi, anche se non so se ci siano degli svantaggi nell'utilizzo di questo suggerimento per la query.
SELECT MIN(CreatedDate)
FROM MyTable
WHERE SomeIndexedValue = 1
OPTION(querytraceon 8649)
Preferirei comunque un tempo di esecuzione più breve poiché la query ha lo scopo di popolare un valore in base alla selezione dell'utente, quindi idealmente dovrebbe essere istantanea come la query raggruppata. In questo momento sto solo avvolgendo la mia domanda, ma so che non è davvero una soluzione ideale.
SELECT Min(CreatedDate)
FROM
(
SELECT Min(CreatedDate) as CreatedDate
FROM MyTable WITH (NOLOCK)
WHERE SomeIndexedValue = 1
GROUP BY CreatedDate
) as T
Modifica n. 2
In risposta alla richiesta di Martin per ulteriori informazioni :
Entrambi CreatedDate
e SomeIndexedValue
hanno un indice separato non univoco, non cluster su di essi. SomeIndexedValue
è in realtà un campo varchar (7), anche se memorizza un valore numerico che punta al PK (int) di un'altra tabella. La relazione tra le due tabelle non è definita nel database. Non dovrei affatto cambiare il database e posso solo scrivere query che interrogano i dati.
MyTable
contiene oltre 3 milioni di record e ad ogni record viene assegnato un gruppo a cui appartiene ( SomeIndexedValue
). I gruppi possono essere ovunque da 1 a 200.000 record
MAXDOP
imposta il massimo grado di parallelismo, che limita il numero di processori che la query può utilizzare. Questo in sostanza renderebbe la seconda query lenta quanto la prima, poiché rimuove le sue capacità di usare il parallelismo, che non è quello che voglio.