SQL Server 2019 e la funzione Approx_Count_Distinct

Ciao a tutti!

Per introdurre la novità di cui parleremo oggi partiamo da un esempio.

Supponiamo abbiate una tabella dentro al vostro gestionale in cui vengano registrate tutte le vendite effettuate.
Concettualmente le colonne di questa tabella saranno: il cliente che effettua l'acquisto, l'articolo che il cliente acquista, la quantità ed il prezzo.

Supponiamo per semplicità che tale tabella abbia questa struttura:

CREATE TABLE ELENCOVENDITE
(ID INT IDENTITY(1,1),
 CLIENTE VARCHAR(80),
 ARTICOLO VARCHAR(80),
 QUANTITA FLOAT,
 PREZZO FLOAT)


Supponiamo adesso che vogliate sapere il numero di articoli acquistati per ogni cliente.
Semplice direte voi scrivendo il comando sotto:

SELECT COUNT(DISTINCT(CLIENTE)) FROM ELENCOVENDITE


Bravi risposta esatta!

Non vi stupirà però sapere che questa operazione, che in apparenza sembra essere così semplice, richiede invece tante risorse.
Richiede infatti di scorrere tutte le righe della nostra tabella.

Ma vediamolo....

Eseguiamo la select count distinct riportata sopra:

Table 'ELENCOVENDITE'. Scan count 9, logical reads 28224, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.

(1 riga interessata)

Tempo di esecuzione SQL Server:
 tempo di CPU = 2126 ms, tempo trascorso = 372 ms.
  


Come potete vedere abbiamo letto ben 28224 pagine dalla tabella Elencovendite.
Abbiamo impiegato 2126 ms di tempo di CPU e 372 ms di tempo totale.

 

La funzione APPROX_COUNT_DISTINCT

Possiamo ora dire che Microsoft a partire da SQL Server 2019 ha introdotto una nuova funzione che si chiama APPROX_COUNT_DISTINCT.
L'obbiettivo di questa funzione è di restituire il conteggio distinto dei valori "con una certa approssimazione".
Se quindi non abbiamo la necessità di sapere il valore esatto dei valori distinti ma ci accontentiamo di una piccola approssimazione (qualche punto percentuale),  allora usando questa funzione avremo un tempo di esecuzione minore.

Ma è vero? Proviamolo!

Scriviamo ed eseguiamo questo comando T-SQL:


SELECT APPROX_COUNT_DISTINCT(CLIENTE) FROM ELENCOVENDITE

Ed ecco i risultati:

Table 'ELENCOVENDITE'. Scan count 9, logical reads 28224, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.

(1 riga interessata)

Tempo di esecuzione SQL Server:
 tempo di CPU = 2158 ms, tempo trascorso = 379 ms.



Attenzione! Questa volta a sorpresa ed a differenza di quanto dichiarato dalla stessa Microsoft non abbiamo ottenuto nessun miglioramento.
Ci aspettavamo in realtà una riduzione del tempo di CPU ma anche effettuando ulteriori prove non siamo riusciti ad ottenere nessun miglioramente del tempo di esecuzione.
Non ci diamo tuttavia per vinti ...indagheremo e risolveremo l'arcano!


Ciao a tutti

Alla prossima!

Luca Biondi @ SQLServerPerformance blog!


 





Next post: T-SQL & quando gli update non aggiornano nessuna riga

Previous post:SQL Server 2019 ed il Batch Mode on Rowstore

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!