Piano di esecuzione
di una query

Riportiamo integralmente in questo articolo una delle nuove domande sul piano di esecuzione di una query che abbiamo aggiunto al corso-test su Udemy, spiegando in seguito la risposta. Lo studio del piano di esecuzione di una query è uno step imprescendibile per valutarne le perfomance e le possibilità di tuning.

Creiamo una tabella Clienti con tre colonne

CREATE TABLE Clienti (NumeroCliente int not null,
Nome varchar(100) not null,
Cognome varchar(100) not null);

Popoliamola con un po’ di record

INSERT INTO Clienti (NumeroCliente, Nome, Cognome)
VALUES
(1, ‘Francesco’, ‘Marino’),
(2, ‘Francesco’, ‘Gialli’),
(3, ‘Francesco’, ‘Verdi’),
(4, ‘Carlo’, ‘Rossi’);

Aggiungiamo una chiave primaria sulla colonna NumeroCliente  e una struttura d’appoggio sulla colonne Nome .

ALTER TABLE Clienti ADD PRIMARY KEY (NumeroCliente);

CREATE NONCLUSTERED INDEX IndiceNome ON Clienti(nome);

Consideriamo queste tre query con una struttura molto simile:

  1. SELECT Nome
    FROM Clienti
    GROUP BY Nome;
  2. SELECT Cognome
    FROM Clienti
    GROUP BY Cognome;
  3. SELECT NumeroCliente
    FROM Clienti
    GROUP BY NumeroCliente;

Quante tra queste query sono risolte esclusivamente con una scansione del clustered index? In quali è presente un algoritmo di ordinamento? Esaminiamole una alla volta, in basso sono riportati i piani di esecuzione.

 

Prima query: SELECT Nome FROM Clienti GROUP BY Nome; 

Le informazioni necessarie per risolvere la query sono contenute tutte nell’indice non clustered costruito sulla colonna nome. In questa struttura d’appoggio i dati sono già ordinati, di conseguenza l’operazione di rimozione dei duplicati sarà immediata. Concludendo, il piano di esecuzione prevederà una semplice scansione ordinata dell’indice (Index Scan) e l’aggregazione dei record uguali (Stream Aggregate) dal costo trascurabile.

 

Seconda query: SELECT Cognome FROM Clienti GROUP BY Cognome;

Sul campo Cognome non è presente nessuna struttura d’appoggio. Il piano d’esecuzione sarà dunque obbligato a scansionare l’intero clustered index. Per rendere più efficiente l’operazione di rimozione dei duplicati sarà inoltre necessario un oneroso ordinamento (78% del costo totale).

 

Terza query: SELECT NumeroCliente FROM Clienti GROUP BY NumeroCliente;

Occorre osservare che non sono necessarie operazioni di rimozione dei duplicati. Sql Server è consapevole che la colonna NumeroCliente è chiave primaria, di conseguenza si limiterà a scansionare i dati.  Tale scansione sarà fatta sull’indice non clustered (invece che sull’indice clustered), probabilmente a causa della sua dimensione ridotta rispetto alla struttura principale che contiene tutte le colonne.

 

Ricapitolando, nessuna delle tre query proposte effettua esclusivamente una scansione del clustered index, mentre una query prevede un operatore di ordinamento (la seconda).

In basso il piano di esecuzione delle tre query.

Articoli correlati

Leggi perché secondo noi il database MySql non rappresenta la scelta migliore per introdurre il linguaggio SQL a studenti che si approcciano per la prima volta a questo linguaggio.