data codes through eyeglasses
Photo by Kevin Ku on Pexels.com

Come ottimizzare le performance di una Query su SQL Server

Le prestazioni dei database sono un fattore cruciale per il successo di qualsiasi applicazione aziendale. In questo articolo, approfondiremo le tecniche di ottimizzazione delle query in SQL Server, concentrandoci su esempi pratici e casi concreti per migliorare le performance.

L’Importanza dell’Ottimizzazione

In un contesto in cui ogni millisecondo conta, l’ottimizzazione delle query diventa essenziale per garantire un’esperienza utente fluida. Non si tratta solo di velocità, ma anche di ridurre l’uso delle risorse del server, migliorare la scalabilità dell’applicazione e, infine, abbattere i costi operativi.

Prima di entrare nei dettagli delle ottimizzazioni pratiche, è fondamentale comprendere alcuni concetti base. In SQL Server, l’ottimizzazione si fonda su tre pilastri principali:

  1. La gestione degli indici
  2. La scrittura efficiente delle query
  3. La gestione ottimale delle risorse del server


Questi concetti, sebbene possano sembrare complessi all’inizio, diventano più chiari con la pratica e la formazione. A questo link, trovi un corso su SQL Server che offre un’approfondita esplorazione delle tecniche di ottimizzazione, con esempi pratici e casi reali.

Analisi dei Piani di Esecuzione

Un potente strumento di ottimizzazione in SQL Server è l’analisi dei piani di esecuzione. Il piano di esecuzione è una “mappa” che mostra come SQL Server esegue una query, evidenziando i possibili colli di bottiglia. Per visualizzare il piano, basta cliccare sull’icona “Display Estimated Execution Plan” in SQL Server Management Studio (SSMS) o abilitare SET STATISTICS XML ON prima della query.

Esempio pratico di analisi del piano di esecuzione:

Considera questa query non ottimizzata:

-- Query non ottimizzata
SELECT *
FROM Vendite
WHERE YEAR(DataVendita) = 2024;

In questo caso, la query non è SARGable (Search ARGument ABLE), poiché utilizza una funzione sulla colonna DataVendita, impedendo l’uso efficiente degli indici. Il piano di esecuzione mostrerà un Table Scan, un’operazione costosa che esamina tutte le righe della tabella.
La versione ottimizzata sarebbe:

-- Query ottimizzata e SARGable
SELECT *
FROM Vendite
WHERE DataVendita >= '2024-01-01'
AND DataVendita < '2025-01-01';

In questo caso, il piano di esecuzione mostrerà un Index Seek, che sfrutta l’indice sulla colonna DataVendita per ottenere risultati più veloci.

Esempi Pratici di Ottimizzazione

Caso 1: L’Uso Improprio di SELECT *

Una pratica comune ma inefficiente è l’utilizzo indiscriminato di SELECT *, che recupera tutte le colonne anche quando ne servono solo alcune. Ecco un esempio di query non ottimizzata:

Query non ottimizzata:

-- Query non ottimizzata
SELECT *
FROM Ordini o
INNER JOIN Clienti c ON o.ClienteID = c.ClienteID
INNER JOIN DettagliOrdine d ON o.OrdineID = d.OrdineID
WHERE o.DataOrdine >= '20240101';

Questa query recupera tutte le colonne da tre tabelle, ma possiamo ottimizzarla selezionando solo quelle necessarie:

-- Query ottimizzata
SELECT o.OrdineID,
       o.DataOrdine,
       c.RagioneSociale,
       c.Email,
       d.Quantita,
       d.PrezzoUnitario
FROM Ordini o
INNER JOIN Clienti c ON o.ClienteID = c.ClienteID
INNER JOIN DettagliOrdine d ON o.OrdineID = d.OrdineID
WHERE o.DataOrdine >= '20240101';

Caso 2: Ottimizzazione delle Aggregazioni Multiple

Immagina di avere una tabella Vendite e di voler calcolare il totale, la media e il numero di vendite per ogni prodotto. Una query non ottimizzata potrebbe sembrare così:

Query non ottimizzata:

-- Query non ottimizzata con più subquery
SELECT ProdottoID,
       (SELECT SUM(ImportoVendita)
        FROM Vendite
        WHERE ProdottoID = v.ProdottoID) as TotaleVendite,
       (SELECT AVG(ImportoVendita)
        FROM Vendite
        WHERE ProdottoID = v.ProdottoID) as MediaVendite,
       (SELECT COUNT(*)
        FROM Vendite
        WHERE ProdottoID = v.ProdottoID) as NumeroVendite
FROM Prodotti v;

In questa query, vengono eseguite tre subquery separate per ciascun aggregato (somma, media e conteggio) per ogni prodotto. Questo approccio è inefficiente perché per ogni prodotto, SQL Server esegue tre scansioni della tabella Vendite.

Una versione ottimizzata della query, che calcola tutte le aggregazioni in una sola scansione della tabella, è la seguente:

-- Query ottimizzata con un'unica scansione
SELECT v.ProdottoID,
       SUM(V.ImportoVendita) as TotaleVendite,
       AVG(V.ImportoVendita) as MediaVendite,
       COUNT(*) as NumeroVendite
FROM Prodotti v
LEFT JOIN Vendite V ON v.ProdottoID = V.ProdottoID
GROUP BY v.ProdottoID;

Come funziona:

  • La query ottimizzata utilizza un JOIN tra la tabella Prodotti e la tabella Vendite, invece di eseguire subquery separate per ogni aggregazione.
  • Le aggregazioni SUM(), AVG() e COUNT() vengono calcolate in un’unica scansione della tabella Vendite (grazie al JOIN), e il GROUP BY consente di ottenere i risultati per ciascun prodotto.
  • Questo approccio è molto più efficiente poiché riduce il numero di operazioni di lettura sulla tabella Vendite, migliorando notevolmente le prestazioni rispetto alla versione con subquery multiple.

In sintesi, l’ottimizzazione qui è dovuta all’eliminazione di subquery ridondanti e all’esecuzione di aggregazioni in un solo passaggio, migliorando l’efficienza della query.

L’Importanza degli Indici

Gli indici sono uno degli strumenti più potenti per migliorare le prestazioni delle query, ma devono essere utilizzati con attenzione. Un indice ben progettato può velocizzare enormemente le operazioni di ricerca e filtro, mentre un uso eccessivo o improprio degli indici può appesantire le performance del database, rallentando le operazioni di inserimento, aggiornamento ed eliminazione dei dati.

Se una query frequente filtra più colonne, come DataOrdine e ClienteID, un indice composito può migliorare le prestazioni rispetto a più indici separati. Supponiamo che tu abbia una query del tipo:

-- Query senza indice composito
SELECT *
FROM Ordini
WHERE DataOrdine >= '2024-01-01'
AND ClienteID = 12345;

Creare due indici separati, uno per DataOrdine e uno per ClienteID, non sarà altrettanto efficiente quanto un singolo indice che copre entrambe le colonne.

-- Creazione di un indice composito
CREATE INDEX IX_Ordini_DataCliente ON Ordini(ClienteID, DataOrdine);

Un dettaglio importante da considerare è che nell’indice la colonna ClienteID, che viene filtrata con un’operazione di uguaglianza, appare prima della colonna DataOrdine, che viene filtrata con una condizione di maggiore o uguale.

Un indice composito consente a SQL Server di trovare rapidamente le righe che soddisfano entrambe le condizioni, senza dover eseguire una ricerca separata per ciascuna colonna. In alcuni casi questo approccio è molto più veloce rispetto all’utilizzo di due indici distinti.

Conclusioni e Best Practices

Ottimizzare le query è un processo che richiede esperienza e una buona conoscenza di come SQL Server gestisce le richieste. Alcune best practices fondamentali per l’ottimizzazione includono:

  • Utilizzare i piani di esecuzione per identificare e correggere i colli di bottiglia
  • Scrivere query SARGable per sfruttare al meglio gli indici
  • Evitare l’uso di SELECT * e selezionare solo le colonne necessarie
  • Preferire l’uso di JOIN rispetto alle subquery
  • Creare indici mirati, basati sui pattern di query più comuni

L’ottimizzazione delle query è un processo continuo che richiede monitoraggio costante e adattamento alle modifiche nel carico di lavoro e nelle necessità aziendali. Un database ben ottimizzato non solo migliora la velocità delle query, ma assicura anche una gestione efficace delle risorse, migliorando la scalabilità e riducendo i costi operativi.

Riguardo a: Salvo Cirmi (Tux1)

Un pinguino intraprendente che dopo diversi anni di "servizio" online (e soprattutto delle guide) ha acquisito conoscenze non di poco conto sui settori Android, Linux e Windows. Le mie specialità sono il modding e le review. Nel tempo libero (che è raro trovare) suono il piano, mi diverto effettuando modding e provando distribuzioni Linux, BSD ed altre.

Guarda anche..

an artist s illustration of artificial intelligence ai this illustration depicts language models which generate text it was created by wes cockx as part of the visualising ai project l

Come utilizzare AI per trasformare il testo in presentazione: Guida Completa

efficace, ma spesso la loro creazione richiede tempo e competenze specifiche. Tuttavia, grazie all’intelligenza artificiale …

Ads Blocker Image Powered by Code Help Pro

Usi un Adblock, non è una bella cosa.

Siti come il mio faticano ad andare avanti senza pubblicità. Se non vuoi che il sito venga chiuso, per favora, disabilita il blocco annunci. Grazie.