Seq Scan, Index Scan e Index-Only
Perché il planner sceglie ciascun metodo e cosa rivela sulla query.
Seq Scan, Index Scan e Index-Only è una lezione Coding Interview Prep gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Coding Interview Prep, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Coding Interview Prep include 4 lezioni in totale.
Tre modi per leggere una tabella
Quando il planner ha bisogno di righe da una tabella, sceglie uno dei tre metodi di accesso seguenti; gli intervistatori si aspettano che li sappia elencare tutti:
- Seq Scan: legge ogni riga della tabella dall'inizio alla fine.
- Index Scan: percorre un indice per trovare le righe corrispondenti, quindi recupera ciascuna riga dalla tabella.
- Index-Only Scan: restituisce il risultato interamente dall'indice, senza accedere alla tabella.
Capire perché il planner sceglie ciascun metodo è il cuore di questa lezione e una domanda da senior quasi garantita.
Che cosa fa una scansione sequenziale
Una Seq Scan legge le pagine della tabella una dopo l'altra e applica l'eventuale filtro a ogni riga. Non viene consultato alcun indice.
Può sembrare una scelta negativa, ma spesso è quella giusta. Le letture sequenziali sono veloci per il disco (non richiedono salti casuali), quindi, quando una query restituisce una grande parte della tabella, leggere tutto è più efficiente che attraversare un indice milioni di volte.
Nell'esempio si esegue una scansione di orders e si conservano le righe per cui amount > 100. Se la maggior parte degli ordini supera 100, una scansione sequenziale è la scelta corretta.
EXPLAIN SELECT * FROM orders WHERE amount > 100;
Seq Scan on orders (cost=0.00..18334.00 rows=900000 width=64)
Filter: (amount > 100)Che cosa fa una scansione con indice
Una Index Scan usa un B-tree per raggiungere direttamente le chiavi corrispondenti, quindi legge le relative righe dall'heap della tabella.
È particolarmente vantaggiosa quando il filtro è selettivo e restituisce una piccola parte della tabella. Cercare 5 righe tramite un indice è più efficiente che leggere 10 milioni di righe.
Il piano indica l'indice utilizzato. Ogni corrispondenza richiede una ricerca nell'indice e un recupero dall'heap della tabella (una lettura casuale), quindi le scansioni con indice perdono il loro vantaggio quando restituiscono troppe righe.
EXPLAIN SELECT * FROM orders WHERE customer_id = 42;
Index Scan using idx_orders_customer on orders
(cost=0.42..38.50 rows=12 width=64)
Index Cond: (customer_id = 42)La selettività determina la scelta
Il concetto fondamentale alla base di tutto questo è la selettività: la frazione di righe che un predicato mantiene.
- Alta selettività (corrispondono poche righe, ad esempio con un ID univoco) favorisce una Index Scan.
- Bassa selettività (corrispondono molte righe, ad esempio con
status IS NOT NULL) favorisce una Seq Scan.
Una regola pratica comune è che, quando una query restituisce più o meno del 5-10% di una tabella, il planner spesso preferisce una scansione sequenziale, perché i recuperi casuali dall'heap richiesti da un indice diventano più costosi della lettura ordinata dell'intera tabella.
La scansione solo indice
Una Index-Only Scan è la più veloce dei tre metodi. Se ogni colonna necessaria alla query è già contenuta nell'indice, il motore non accede mai all'heap della tabella.
La query dell'esempio seleziona solo customer_id e applica un filtro su di esso, mentre l'indice è definito su customer_id. Tutti i dati necessari si trovano nell'indice, quindi Postgres segnala Index Only Scan.
In questo modo si evitano le letture casuali dall'heap che rallentano una normale scansione con indice: un enorme vantaggio sulle tabelle con righe larghe.
EXPLAIN SELECT customer_id FROM orders WHERE customer_id = 42;
Index Only Scan using idx_orders_customer on orders
(cost=0.42..8.44 rows=12 width=4)
Index Cond: (customer_id = 42)La particolarità della visibility map
Gli intervistatori apprezzano molto questa sfumatura. Una scansione solo indice deve comunque verificare che ogni riga sia visibile alla transazione (MVCC), ma l'indice da solo non memorizza le informazioni sulla visibilità.
Postgres usa la visibility map: se una pagina è contrassegnata come all-visible, evita l'accesso all'heap; altrimenti deve recuperare comunque la riga dall'heap. Il piano mostra Heap Fetches: N.
Per questo una tabella appena aggiornata può mostrare molti recuperi dall'heap e scansioni solo indice lente, finché VACUUM non aggiorna la visibility map.
Index Only Scan using idx_orders_customer on orders
(actual time=0.01..0.03 rows=12 loops=1)
Heap Fetches: 0Scansioni bitmap: una via di mezzo
Esiste un quarto metodo che compare spesso: la Bitmap Heap Scan. Il planner la sceglie quando un predicato corrisponde a più righe di quante ne gestirebbe una normale scansione con indice, ma a meno righe di un'intera tabella.
Prima costruisce dall'indice una bitmap delle posizioni delle righe corrispondenti (Bitmap Index Scan), poi recupera le pagine dell'heap in ordine fisico anziché in ordine casuale. I recuperi ordinati sono molto meno costosi delle letture sparse di una normale scansione con indice.
Bitmap Heap Scan on orders (cost=12.0..520.0 rows=8000)
Recheck Cond: (status = 'pending')
-> Bitmap Index Scan on idx_orders_status
(cost=0..12 rows=8000)
Index Cond: (status = 'pending')Perché il planner ha ignorato il Suo indice
Una domanda classica nei colloqui: ho aggiunto un indice, ma il piano esegue ancora una Seq Scan: perché? Le ragioni comuni sono:
- Il predicato non è selettivo: la scansione è effettivamente più economica.
- Una funzione avvolge la colonna:
WHERE lower(email) = ...non può usare un normale indice suemail. - Una incompatibilità di tipo impone una conversione implicita che rende inutilizzabile l'indice.
- Statistiche obsolete: esegua
ANALYZE. - La tabella è piccolissima: la scansione di poche pagine è più efficiente dell'overhead dell'indice.
Diagnosi con esempio
Supponga che orders abbia un indice su created_at, ma che questa query esegua comunque una scansione sequenziale:
La causa è DATE(created_at). Racchiudere la colonna in una funzione significa che l'indice sulla colonna created_at originale non può essere utilizzato. La soluzione consiste nel riscrivere il predicato come un predicato di intervallo che lasci la colonna invariata, oppure nel creare un indice su espressione per DATE(created_at).
-- Slow: function on the indexed column
WHERE DATE(created_at) = '2026-01-01'
-- Fast: bare column, range uses the index
WHERE created_at >= '2026-01-01'
AND created_at < '2026-01-02'Confronto tra i metodi
Tenga a mente questo confronto per il colloquio:
- Seq Scan: ideale quando restituisce una grande parte delle righe; I/O sequenziale.
- Index Scan: ideale per ricerche selettive; attraversamento dell'indice più recuperi casuali dall'heap.
- Bitmap Heap Scan: numero intermedio di corrispondenze; dall'indice alla bitmap, quindi letture ordinate dell'heap.
- Index-Only Scan: la più veloce quando l'indice contiene tutte le colonne necessarie e le pagine sono tutte visibili.
Il planner sceglie in base al cost stimato, determinato principalmente dalla selettività e dalle statistiche.
Forzare un test (e perché non farlo in produzione)
Per dimostrare un concetto durante lo sviluppo, può temporaneamente orientare il planner: SET enable_seqscan = off; lo costringe a preferire gli indici, così può confrontare i piani.
Si tratta di un espediente diagnostico, mai di una soluzione da usare in produzione. Nei colloqui, specifichi che le soluzioni reali sono statistiche migliori, un indice appropriato o la riscrittura del predicato, non la disattivazione globale delle funzionalità del planner.
SET enable_seqscan = off;
EXPLAIN ANALYZE SELECT * FROM orders WHERE amount > 100;
SET enable_seqscan = on;Verifica rapida
Una query seleziona solo email e applica un filtro su email; esiste inoltre un indice B-tree su email. Il piano mostra Index Only Scan. Perché è più veloce di una normale Index Scan?
Riepilogo
Punti chiave sui metodi di accesso:
- Seq Scan è la scelta migliore per le query a bassa selettività; Index Scan è la scelta migliore per quelle selettive.
- Index-Only Scan evita l'heap quando l'indice contiene tutte le colonne necessarie: presti attenzione a
Heap Fetchese alla visibility map. - Bitmap Heap Scan costituisce una soluzione intermedia, recuperando le pagine dell'heap in ordine fisico.
- Il planner decide in base a selettività e statistiche; le funzioni sulle colonne, le incompatibilità di tipo e le statistiche obsolete sono i motivi per cui un indice viene ignorato.
Domande Frequenti
La lezione «Seq Scan, Index Scan e Index-Only» è gratuita?
Sì — il testo completo di «Seq Scan, Index Scan e Index-Only» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Coding Interview Prep, passa a CoddyKit PRO. Il corso Coding Interview Prep include 4 lezioni in totale.
Cosa imparerò in «Seq Scan, Index Scan e Index-Only»?
Perché il planner sceglie ciascun metodo e cosa rivela sulla query. Eserciti Coding Interview Prep con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Coding Interview Prep?
Non è richiesta alcuna esperienza precedente. Coding Interview Prep su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Seq Scan, Index Scan e Index-Only»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Coding Interview Prep?
Sì. Ogni lezione Coding Interview Prep include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Leggere un piano EXPLAIN
- Seq Scan, Index Scan e Index-Only
- Algoritmi di join: Nested Loop, Hash, Merge
- Individuare e risolvere le query lente