SQL Order of Operations – In quale ordine MySQL esegue le query?
Clicca per iniziare, gratis.
Conoscere i bit e i byte dell’ordine delle operazioni di una query SQL può essere molto prezioso, in quanto può facilitare il processo di scrittura di nuove query, mentre è anche molto utile quando si cerca di ottimizzare una query SQL.
Se state cercando la versione breve, questo è l’ordine logico delle operazioni, noto anche come ordine di esecuzione, per una query SQL:
- DA, incluse le JOIN
- WHERE
- GROUP BY
- HAVING
- WINDOW funzioni
- SELECT
- DISTINCT
- UNION
- ORDER BY
- LIMIT e OFFSET
Ma la realtà non è così facile e diretta. Come abbiamo detto, lo standard SQL definisce l’ordine di esecuzione delle diverse clausole di query SQL. Detto questo, i database moderni stanno già sfidando questo ordine predefinito applicando alcuni trucchi di ottimizzazione che potrebbero cambiare l’ordine effettivo di esecuzione, anche se devono finire per restituire lo stesso risultato come se stessero eseguendo la query nell’ordine di esecuzione predefinito.
Perché dovrebbero farlo? Beh, può essere sciocco se il database recupera prima tutti i dati menzionati nella clausola FROM (incluse le JOIN), prima di esaminare la clausola WHERE e i suoi indici. Queste tabelle possono contenere molti dati, quindi potete immaginare cosa succederebbe se l’ottimizzatore del database si attenesse all’ordine tradizionale delle operazioni di una query SQL.
Guardiamo ogni parte della query SQL secondo il loro ordine di esecuzione.
FROM e JOINs
Le tabelle specificate nella clausola FROM (incluse le JOINs), saranno valutate per prime, per determinare l’intero set di lavoro che è rilevante per la query. Il database unirà i dati di tutte le tabelle, secondo le clausole JOINs ON, mentre recupera i dati dalle subquery, e potrebbe anche creare alcune tabelle temporanee per contenere i dati restituiti dalle subquery in questa clausola.
In molti casi però, l’ottimizzatore del database sceglierà di valutare prima la parte WHERE, per vedere quale parte dell’insieme di lavoro può essere lasciata fuori (preferibilmente usando gli indici), così non gonfierà troppo l’insieme di dati se non è davvero necessario.
Clausola WHERE
La clausola WHERE sarà la seconda ad essere valutata, dopo la clausola FROM. Abbiamo l’insieme di dati di lavoro sul posto, e ora possiamo filtrare i dati secondo le condizioni della clausola WHERE.
Queste condizioni possono includere riferimenti ai dati e alle tabelle della clausola FROM, ma non possono includere alcun riferimento agli alias definiti nella clausola SELECT, poiché quei dati e quegli alias potrebbero non ‘esistere’ ancora in quel contesto, poiché quella clausola non è stata ancora valutata dal database.
Inoltre, una trappola comune per la clausola WHERE sarebbe quella di provare a filtrare i valori aggregati nella clausola WHERE, per esempio con questa clausola: “WHERE sum(available_stock) > 0”. Questa dichiarazione fallirà l’esecuzione della query, perché le aggregazioni saranno valutate più avanti nel processo (vedere la sezione GROUP BY qui sotto). Per applicare condizioni di filtraggio sui dati aggregati, dovresti usare la clausola HAVING e non la clausola WHERE.
Clausola GROUP BY
Ora che abbiamo filtrato il set di dati usando la clausola WHERE, possiamo aggregare i dati secondo una o più colonne che appaiono nella clausola GROUP BY. Raggruppare i dati è in realtà dividerli in diversi pezzi o bucket, dove ogni bucket ha una chiave e una lista di righe che corrispondono a quella chiave. Non avere una clausola GROUP BY è come mettere tutte le righe in un unico enorme secchio.
Una volta aggregati i dati, è possibile utilizzare funzioni di aggregazione per restituire un valore per gruppo per ciascuno dei secchi. Tali funzioni di aggregazione includono COUNT, MIN, MAX, SUM e altre.
Clausola HAVING
Ora che abbiamo raggruppato i dati usando la clausola GROUP BY, possiamo usare la clausola HAVING per filtrare alcuni bucket. Le condizioni nella clausola HAVING possono fare riferimento alle funzioni di aggregazione, quindi l’esempio che non ha funzionato nella clausola WHERE sopra, funzionerà benissimo nella clausola HAVING: “HAVING sum(available_stock) > 0”.
Poiché abbiamo già raggruppato i dati, non possiamo più accedere alle righe originali a questo punto, quindi possiamo solo applicare condizioni per filtrare interi bucket, e non singole righe in un bucket.
Inoltre, come abbiamo detto nelle sezioni precedenti, gli alias definiti nella clausola SELECT non sono accessibili nemmeno nella sezione, poiché non sono ancora stati valutati dal database (questo è vero nella maggior parte dei database).
Funzioni Window
Se state usando le funzioni Window, questo è il punto in cui verranno eseguite. Proprio come il meccanismo di raggruppamento, anche le funzioni Window eseguono un calcolo su un insieme di righe. La differenza principale è che quando si usano le funzioni Window, ogni riga manterrà la propria identità e non sarà raggruppata in un secchio di altre righe simili.
Le funzioni Window possono essere usate solo nella clausola SELECT o in quella ORDER BY. Si possono usare funzioni di aggregazione all’interno delle funzioni Window, per esempio:
SUM(COUNT(*)) OVER ()
Clausola SELECT
Ora che abbiamo finito di scartare le righe dall’insieme di dati e di raggruppare i dati, possiamo selezionare i dati che vogliamo siano recuperati dalla query al lato client. Potete usare nomi di colonne, aggregazioni e subquery all’interno della clausola SELECT. Tenete a mente che se state usando un riferimento a una funzione di aggregazione, come COUNT(*) nella clausola SELECT, è semplicemente un riferimento a un’aggregazione già avvenuta quando il raggruppamento ha avuto luogo, quindi l’aggregazione stessa non avviene nella clausola SELECT, ma questo è solo un riferimento al suo set di risultati.
Parola chiave DISTINCT
La sintassi della parola chiave DISTINCT è un po’ confusa, perché la parola chiave prende il suo posto prima dei nomi delle colonne nella clausola SELECT. Ma l’effettiva operazione DISTINCT avviene dopo la SELECT. Quando si usa la parola chiave DISTINCT, il database scarterà le righe con valori duplicati dalle righe rimaste dopo il filtraggio e le aggregazioni.
Parola chiave UNION
La parola chiave UNION combina i risultati di due query in un unico risultato. La maggior parte dei database ti permetterà di scegliere tra UNION DISTINCT (che scarterà le righe duplicate dall’insieme di risultati combinato) o UNION ALL (che combina semplicemente gli insiemi di risultati senza applicare alcun controllo di duplicazione).
È possibile applicare l’ordinamento (ORDER BY) e la limitazione (LIMIT) sull’insieme dei risultati dell’UNION, nello stesso modo in cui si può applicare su una normale query.
Clausola ORDER BY
L’ordinamento avviene una volta che il database ha l’intero insieme dei risultati pronto (dopo il filtraggio, il raggruppamento, la rimozione dei duplicati). Una volta che abbiamo questo, il database può ora ordinare l’insieme dei risultati usando colonne, alias selezionati o funzioni di aggregazione, anche se non fanno parte dei dati selezionati. L’unica eccezione è quando si usa la parola chiave DISTINCT, che impedisce l’ordinamento per una colonna non selezionata, poiché in tal caso l’ordine del set di risultati sarà indefinito.
È possibile scegliere di ordinare i dati usando un ordine decrescente (DESC) o ascendente (ASC). L’ordine può essere unico per ciascuna delle parti dell’ordine, quindi il seguente è valido: ORDER BY firstname ASC, age DESC
LIMIT e OFFSET
Nella maggior parte dei casi d’uso (esclusi alcuni come il reporting), vorremmo scartare tutte le righe tranne le prime X righe del risultato della query. La clausola LIMIT, che viene eseguita dopo l’ordinamento, ci permette di fare proprio questo. Inoltre, è possibile scegliere da quale riga iniziare il recupero dei dati e quante escludere, usando una combinazione delle parole chiave LIMIT e OFFSET. L’esempio seguente recupererà 50 righe a partire dalla riga #100: LIMIT 50 OFFSET 100
Clicca per iniziare, gratuitamente.