SQL Server, The Logical Query Processing Phases. In quale ordine viene processata una Query?

Carissimi lettori,

Nell'articolo di oggi parleremo di "Logical Query Processing Phases" ovvero dell'ordine in cui una query viene processata internamente.

Ne parliamo sia perchè è un aspetto utile da conoscere ma sopprattutto perchè ci servirà nei prossimi articoli.

Se siete pronti per imparare (quasi) tutto ma proprio (quasi) tutto sull'argomento di oggi allora ...
Buona lettura!

Il primo concetto che occorre tenere a mente 


Il primo concetto di oggi è che il linguaggio SQL (e quindi anche il nostro T-SQL) è diverso da un linguaggio di programmazione.
Nei linguaggi di programmazione il codice è processato nell’ordine di cui è scritto.
Nel linguaggio SQL non è così: l’ordine in cui una Query viene processata internamente è diverso da quello in cui è scritto.

Diciamolo subito tutto ha inizio dalla FROM!


L’esecuzione di una Query è internamente divisa in varie fasi che sono appunto dette Query Logical Processing Phases.
La prima di questa fasi è la “FROM Phase”

La “FROM Phase”


Durante questa fase vengono identificate tutte le tabelle che devono essere interrogate sul database.
Se sono presenti degli "operatori di tabella" come la JOIN o l’APPLY saranno presenti più tabelle. In questo caso verranno processate da sinistra a destra.

Ogni "operatore di tabella" accetta in input uno o due tabelle e ritorna in output una tabella. Il suo risultato sarà utilizzato come left input per l’operatore di tabella successivo se è presente, in caso contrario sarà l’input della prossima “processing phase”



Ogni table operator è poi costituito da un suo insieme di sottofasi.

Ad esempio l’operatore JOIN ha tre sottofasi che sono:

  • (1-J1) Cartesian Product,
  • (1-J2) ON Filter,
  • (1-J3) Add Outer Rows 

Vediamole più in dettaglio:

La prima delle tre sottofasi J1 effettua il prodotto cartesiano (chiamato anche cross join) tra le due tabelle in input e, come risultato, genera una tabella virtuale che chiamiano VT1-J1.
Questa tabella virtuale contiente una riga per ogni possibile combinazione di una riga della tabella di sinistra ed una riga della tabella di destra.

Nella seconda fase J2 detta di ON filter il predicato che segue viene applicato a tutte le righe della tabella virtuale VT1-J1.
Solo le righe per cui il predicato è vero andranno a far parte della successiva tabella virtuale VT-J2.
Il filtro ON è uno dei tre possibili filtri che sono: ON, WHERE e HAVING.

L'ultima fase J3 è detta di "Add outer Rows" è eseguita solamente nel caso di OUTER JOIN (LEFT, RIGHT o FULL JOIN)

Nel caso di una LEFT OUTER JOIN specifichiamo di voler preservare tutte le righe della tabella di sinistra. In questo caso verranno restituite tutte le righe della tabella virtuale VT1-J2 e in più verranno aggiunte le righe della tabella preservata per cui non viene trovato nessun match.
La tabella risultante è chiamata V1-J3.

Al termine delle tre sottofasi e quindi della fase di From viene generata una tabella virtuale chiamata VT1. 

Come tutte le tabelle virtuali anche questa che non è accessibile all’utente.


La "WHERE Phase"


La fase di WHERE legge direttamente la tabella virtuale VT1 ed è a questa tabella che viene applicato il filtro WHERE.
Tutte le righe per cui il predicato che segue la WHERE è vero vanno a costruire la tabella virtuale VT2.


La "GROUP BY Phase"


Questa fase legge la tabella virtuale VT2 ed associa le righe a dei gruppi secondo il predicato che segue la group by.
Ogni combinazione unica di valori degli attributi viene identificata come un gruppo.
La tabella virtuale VT3 che viene creata consiste quindi nelle righe della tabelle VT2 organizzata in gruppi.


La "HAVING Phase"

La fase di having agisce come un filtro applicato alla tabella virtuale VT3.
Solo i gruppi che soddisfano il predicato che segue l'having vengono ritornati nella tabella virtuale VT4.

Il filtro di Having è il solo filtro che si può applicare ai dati raggruppati.


Ed infine arriva l'ultima fase che è anche quella che noi scriviamo per prima ovvero la fase di SELECT.

La "SELECT Phase"


Compito della fase di SELECT è quello di costruire la tabella che conterrà i dati che abbiamo richiesto. Legge i dati dalla tabella virtuale VT4 ed è divisa in tre sottofasi.

  • (5-1) Evaluate Expressions, 
  • (5-2) Apply DISTINCT Clause, 
  • (5-3) Apply TOP Option. 
La prima sottofase (5-1) detta di Evaluate Expressions legge i dati dalla tabella VT4 e ritorna le colonne base oppure una loro manipolazione come ad esempio MIN(colonna base), YEAR(colonna base)

La sottofase seguente (5-2) detta di Apply DISTINCT Clause avviene qualora venga specificato la clausola DISTINCT.
In questo caso le righe duplicate vengono rimosse dalla tabella virtuale VT5-1 e viene generata la tabella virtuale VT5-2.

L'ultima sottofase (5-3)  detta Apply TOP Option avviene solamemente in presenza della opzione TOP. In questa caso vengono lette le righe da VT5-2 e restituite solamente le righe desiderate: TOP(2) ad esempio farà si che vengano resituite solamente le prime due righe.

Logicamente assieme alla opzione TOP deve essere specificato anche un ordinamento tramite la clausola ORDER BY.

La "ORDER BY Phase"


L'ultima fase è detta di order by e si occupa della presentazione dei dati.
I dati infatti vengono restituiti (presentati) nell'ordine definito dalla clausola order by.

Questa fase ritorna il cursore VC6.
Essendo la fase successiva alla fase di SELECT questa fase è l'unica in cui gli alias di colonna definiti nella select posso venire utilizzati.



Per oggi è tutto.
Scrivetemi se non sono riuscito a spiegarmi in modo chiaro..arà il motivo per migliorare!
Scrivetemi anche se avete dubbi o domande.

Se invece vi è piaciuto allora iscrivetevi a questo blog e ...rimanete in attesa dei prossimi interessantissimi argomenti.

Per oggi è davvero tutto.

Ciao ed alla prossima!


Luca Biondi @ The Cutting Edge SQL Server Performance blog!









Next post: SQL Server, come vedere tutte le proprietà di una tabella con un solo comando

Previous post: NEWS! Edizione Speciale! SQL Server 2019 è arrivato tra di noi!


Comments

I Post più popolari

SQL Server, execution plan and the lazy spool (clearly explained)

SQL Server, datetime vs. datetime2

La clausola NOLOCK. Approfondiamo e facciamo chiarezza!