Poor SQL: quando il codice non è efficiente

Quando parli di “poor SQL”, stai toccando un nervo scoperto per qualsiasi sviluppatore : stai dicendo del codice SQL che è, in buona sostanza, scritto male, inefficiente o non ottimizzato. È il tipo di SQL che può trasformare una query semplice in un incubo di performance, rendere il codice illeggibile e difficile da mantenere, o addirittura portare a risultati errati.

In definitiva, “poor SQL” equivale alla fine codice che costa tempo, risorse e potenzialmente errori. Investire tempo per scrivere e ottimizzare il SQL è cruciale per la salute e le performance di qualsiasi sistema basato su database.

Cosa rende il SQL “Poor” (Povero/Cattivo)?

Un “poor SQL” può manifestarsi in vari modi, ma i problemi principali ricadono generalmente in queste categorie:

1. Inefficienza delle Query (Performance)

Questo è probabilmente il problema più comune e impattante. Un SQL inefficiente rallenta le applicazioni, sovraccarica il database e frustra gli utenti.

  • Scansioni di tabella complete (SELECT * su tabelle grandi): Selezionare tutte le colonne quando ne servono solo poche, o non usare una clausola WHERE su tabelle enormi.
    • Esempio: SELECT * FROM BigCustomerTable; (quando ti servono solo CustomerID e CustomerName).
  • Mancanza o uso scorretto degli indici: Le query che non riescono a usare gli indici (o perché non ci sono, o perché le condizioni le rendono inutilizzabili) ricorrono a scansioni complete, molto più lente.
    • Esempio: SELECT * FROM Prodotti WHERE UPPER(NomeProdotto) = 'PENNA'; (La funzione UPPER applicata alla colonna NomeProdotto può impedire l’uso di un indice su NomeProdotto).
  • Subquery non correlate o poco efficienti: Usare subquery che vengono eseguite più volte inutilmente, o che non sono ottimizzate.
  • Operazioni costose: JOIN su colonne non indicizzate, uso eccessivo di DISTINCT su grandi dataset, o abuso di UNION anziché UNION ALL.
  • Operazioni su grandi quantità di dati: ORDER BY o GROUP BY su colonne senza indici possono richiedere molto tempo e risorse per sortare e raggruppare i dati.
  • NOLOCK usato a sproposito: L’uso di WITH (NOLOCK) (o READ UNCOMMITTED) senza comprenderne le implicazioni può portare a leggere dati non ancora commitati, causando risultati inconsistenti.

2. Illogicità o Risultati Errate

Il SQL può essere “poor” anche se sembra veloce, ma fornisce dati sbagliati o inconsistenti.

  • Mancanza di gestione dei NULL: Come abbiamo visto, i NULL si comportano in modo speciale e non gestirli correttamente può portare a esclusioni inaspettate di righe o calcoli errati.
  • Condizioni di JOIN imprecise: JOIN errati possono portare a prodotti cartesiani involontari (troppe righe) o a perdere righe importanti (troppo poche righe).
  • Aggregazioni errate: Non capire come GROUP BY funziona con le funzioni aggregazione può portare a somme, medie o conteggi che non riflettono la realtà dei dati.

3. Difficoltà di Manutenzione e Leggibilità

Anche un SQL corretto e performante può essere “poor” se nessuno riesce a capirlo.

  • Formattazione incoerente o assente: Query lunghe scritte su una singola riga o con indentazione incomprensibile.
  • Nomi di alias o colonne poco chiari: SELECT a.col1, b.col2 FROM TableA a JOIN TableB b... senza spiegare cosa sono a e b.
  • Logica eccessivamente complessa: Query con troppe subquery annidate, CTE complicate o condizioni WHERE labirintiche.
  • Commenti insufficienti o fuorvianti: La mancanza di commenti per spiegare la logica complessa o commenti che non riflettono più il codice.

4. Violazione delle Best Practice

Ogni database e contesto ha delle best practice, e non seguirle può portare a “poor SQL”.

  • Dipendenza da funzionalità deprecate: Usare sintassi o funzioni che sono state deprecate e che potrebbero essere rimosse nelle future versioni.
  • Mancanza di parametri: Non usare parametri per le query dinamiche, esponendo l’applicazione a rischi di SQL Injection.
  • Non gestire gli errori: Non prevedere e gestire le eccezioni o gli errori che potrebbero verificarsi durante l’esecuzione del SQL.

Come Riconoscere e Migliorare il codice

  1. Analisi del Piano di Esecuzione: Questo è lo strumento più potente. Ti mostra come SQL Server intende eseguire la tua query, dove spende più tempo (scan, seek, sort, join) e se sta usando gli indici correttamente.
  2. Monitoraggio delle Performance: Utilizza strumenti come SQL Server Management Studio (SSMS) Activity Monitor, Performance Monitor, o i report standard di SQL Server per identificare le query più lente.
  3. Refactoring del Codice: Semplifica le query complesse, usa CTE (Common Table Expressions) per rendere il codice più leggibile, e migliora la formattazione.
  4. Ottimizzazione degli Indici: Assicurati che le colonne usate nelle clausole WHERE, JOIN, ORDER BY e GROUP BY abbiano gli indici appropriati.
  5. Test: Testa sempre le tue query con dataset rappresentativi, inclusi casi limite e volumi elevati, per assicurarti che forniscano risultati corretti e performanti.
  6. Formazione e Revisione del Codice: Collaborare con altri sviluppatori e fare code review aiuta a identificare e correggere il “poor SQL” prima che vada in produzione.