Indici del database: i supereroi invisibili della tua app. Spiegati semplicemente con codice Laravel e avvertimenti importanti
Immagina di cercare una parola specifica in un libro di 1.000 pagine — ma il libro non ha né indice all'inizio né indice analitico alla fine. Dovresti leggere ogni pagina. Questo è esattamente ciò che fa il tuo database quando esegue una query su una colonna senza indice.
Gli indici sono i supereroi invisibili della tua applicazione. Quando fanno il loro lavoro, nessuno se ne accorge. Quando mancano, tutto si blocca. Analizziamo cosa sono, come funzionano e — cosa più importante — gli avvertimenti che ogni sviluppatore deve conoscere.
📚 Cos'è un indice del database?
Un indice del database è una struttura dati speciale (di solito un B-tree) che il database mantiene accanto ai dati della tua tabella. Memorizza una copia ordinata di una o più colonne, più puntatori alle righe originali.
Pensalo come l'indice alfabetico alla fine di un manuale: invece di scansionare ogni pagina, salti direttamente alla voce rilevante.
🎯 Perché gli indici contano
- Velocizzano le clausole WHERE — trovare righe tramite una condizione diventa O(log n) invece di O(n).
- Velocizzano le operazioni JOIN — le chiavi esterne traggono enormi benefici dagli indici.
- Velocizzano ORDER BY — se l'ordinamento corrisponde a un indice, non è necessario alcun ordinamento aggiuntivo.
- Garantiscono l'unicità — gli indici univoci garantiscono l'integrità dei dati a livello di archiviazione.
Senza un indice, MySQL/PostgreSQL deve eseguire una scansione completa della tabella. Su una tabella con milioni di righe, è la differenza tra 5 ms e 5 secondi.
🛠 Creare indici in Laravel
Il sistema di migrazioni di Laravel rende la creazione degli indici pulita ed espressiva.
1. Indice su una singola colonna:
2. Indice univoco:
3. Indice composito (più colonne):
4. Indice con nome personalizzato:
5. Chiave esterna con indice automatico:
🔍 Come verificare che un indice venga utilizzato
Usa EXPLAIN per vedere il piano di esecuzione:
In Laravel:
Cerca Index Scan o Index Only Scan — bene. Cerca Seq Scan — male, a meno che la tabella non sia minuscola.
⚠️ Avvertimenti importanti che ogni sviluppatore deve conoscere
1. Gli indici rallentano le scritture
Ogni INSERT, UPDATE e DELETE deve anche aggiornare ogni indice su quella tabella. Una tabella con 10 indici esegue le scritture circa 10 volte più lentamente di una tabella senza. Indicizza solo le colonne che interroghi, non le colonne che immagini di poter interrogare.
2. La regola del "prefisso più a sinistra" per gli indici compositi
Un indice su (a, b, c) può essere usato per query su a, (a, b) o (a, b, c). Non può essere usato efficientemente per query solo su b o (b, c). L'ordine conta.
3. Gli indici su colonne a bassa selettività sono inutili
Una colonna booleana con il 99% di true e l'1% di false è un cattivo candidato per l'indice. L'ottimizzatore spesso lo ignorerà ed eseguirà comunque una scansione completa, perché scansionare l'indice più cercare le righe costa più che scansionare semplicemente la tabella.
4. Le funzioni sulle colonne indicizzate uccidono l'indice
Soluzioni: memorizza dati normalizzati, o usa indici funzionali/espressione (PostgreSQL li supporta; MySQL 8+ li supporta).
5. Troppi indici sono dannosi quanto troppo pochi
Ogni indice occupa spazio su disco e rallenta le scritture. Ancora più importante, l'ottimizzatore deve considerare più opzioni quando pianifica una query, il che può portare a decisioni peggiori. Controlla regolarmente i tuoi indici.
6. Gli indici inutilizzati sono puro overhead
Trova gli indici che non vengono mai usati ed eliminali. In PostgreSQL:
In MySQL:
7. La selettività dell'indice è più importante del numero di indici
Un indice è più prezioso quando filtra fino a una piccola frazione di righe. Una query che restituisce l'1% di una tabella ne beneficia enormemente. Una query che restituisce l'80% no — il database probabilmente scansionerà la tabella invece.
🚀 Uno scenario realistico di ottimizzazione in Laravel
Considera un'app e-commerce con una pagina lenta "ordini recenti per utente":
Su una tabella con 5 milioni di ordini, questa query potrebbe richiedere secondi. Aggiungi un indice composito:
Ora la stessa query viene eseguita in millisecondi a una cifra, perché l'indice fornisce sia il filtro che l'ordine di ordinamento.
📊 Cheat sheet degli indici
- Chiavi esterne → indicizza sempre.
- Colonne filtrate frequentemente → indicizza se selettive.
- Colonne di ordinamento in ORDER BY → indicizza se usate spesso.
- Colonne a bassa selettività (booleani, stati con pochi valori) → di solito da evitare.
- Ordine negli indici compositi → colonne più selettive / più usate per prime, seguendo la regola del prefisso più a sinistra.
- Controlla regolarmente → elimina gli indici inutilizzati; costano più di quanto danno.
💡 Consigli pratici
- Inizia con le chiavi esterne. Sono gli indici con il ROI più alto che aggiungerai mai.
- Misura prima e dopo. Usa
EXPLAIN ANALYZEper confermare il miglioramento. - Testa con dati di dimensioni di produzione. Una tabella di test da 1.000 righe non rivelerà mai un problema di indice.
- Osserva il percorso di scrittura. Se gli inserimenti rallentano, uno dei tuoi indici potrebbe essere il colpevole.
- Preferisci meno indici compositi ben scelti a molti indici a colonna singola.
- Non indicizzare per intuizione. Indicizza ciò di cui il pianificatore di query ha effettivamente bisogno.
🔗 Conclusione
Gli indici sono il motore silenzioso delle applicazioni ad alte prestazioni. Trasformano query che strisciano in ricerche istantanee, proteggono il tuo database da carichi incontrollati e supportano silenziosamente ogni pagina veloce che i tuoi utenti vedono.
Ma non sono gratuiti. Ogni indice è uno scambio: velocità di lettura in cambio di costo di scrittura e spazio su disco. Aggiungili deliberatamente, verifica che vengano usati e pulisci quelli che non lo sono. Padroneggia questa disciplina, e la tua applicazione scalerà — elegantemente, invisibilmente e a velocità.