Query vs Scan in DynamoDB
Query legge una singola collezione di Item per partition key (restringendo facoltativamente la
sort key); Scan legge l'intera tabella e filtra in seguito. Sembrano
simili nell'API ma fatturano — e scalano — in modo completamente diverso.
Quando dovrei usare Query vs Scan in DynamoDB?
Usa Query ogni volta che puoi indicare la partizione di cui hai bisogno — legge una sola e fattura solo gli Item corrispondenti. Ricorri a Scan solo per export una tantum o tabelle piccole; legge ogni Item e fattura l'intera tabella prima che venga eseguita qualsiasi FilterExpression. Con dati reali, Query vince.
- Query è mirata: paghi per gli Item nella partizione corrispondente.
- Scan è esaustiva: paghi per leggere ogni Item, poi ne scarti la maggior parte con una
FilterExpressionche gira dopo che la lettura è stata conteggiata.
Su una tabella di dimensioni reali, uno Scan con un filtro è il classico trabocchetto del "perché la mia
bolletta è enorme e la mia latenza è peggio di RDS".
Affiancati
| Query | Scan | |
|---|---|---|
| Letture | Una partizione (per PK) | Ogni Item della tabella |
| Capacità fatturata | Item corrispondenti nella partizione | Intera tabella, prima del filtro |
FilterExpression | Applicata dopo la lettura — comunque fatturata per la lettura | Idem — il filtro non riduce mai il costo |
| Latenza | Costante al crescere della tabella | Cresce con la dimensione della tabella |
| Paginazione | 1 MB/pagina → LastEvaluatedKey | 1 MB/pagina; parallelizzabile |
| Usala per | Pattern di accesso noti | Export una tantum, piccole tabelle di config |
La trappola chiave: una FilterExpression gira dopo che DynamoDB ha conteggiato la lettura, su
entrambe le operazioni. Uno Scan che "restituisce 10 righe" può fatturare la lettura di un milione —
il filtro è una comodità, mai un controllo dei costi.
Usa Query
Query PK = "USER#42" AND SK begins_with "ORDER#"
Se ti ritrovi a ricorrere a Scan per rispondere a un pattern di accesso comune, è
un segnale di modellazione: aggiungi un Global Secondary Index così il
pattern diventa una Query.
La scelta si riduce a una domanda — sai indicare la partizione che ti serve?
Se conosci la chiave fai una Query; altrimenti aggiungi un GSI per renderla tale, e
ricorri allo Scan solo quando nessuna chiave è adatta.
Quando Scan va bene
Export una tantum, piccole tabelle di config e job in background che paginano deliberatamente
l'intera tabella. Usa Segment/TotalSegments per suddividere uno Scan tra più
worker (uno scan parallelo) quando devi davvero leggere tutto.
Un riflessivo SELECT * FROM table su DynamoDB è lo stesso anti-pattern travestito
da PartiQL — si compila in uno Scan. Quando hai davvero bisogno di analisi tra più Item
(un GROUP BY, un JOIN, un aggregato), il Workbench SQL di DynoTable li esegue
lato client su un insieme di risultati limitato invece di martellare la tabella.
Stima le unità di lettura che ciascun pattern costerà con il calcolatore di capacità, e prova DynoTable per eseguire e ispezionare queste query sulle tue tabelle.