Come funzionano gli internals di storage di DynamoDB
DynamoDB è una hash table i cui valori sono alberi ordinati, distribuiti tra le macchine in tre Availability Zone. Due strutture dati fanno quasi tutto il lavoro: un hash sulla partition key sceglie una macchina, un B-tree sulla sort key ordina gli item al suo interno.
Come archivia i dati DynamoDB?
DynamoDB archivia i tuoi dati come una gigantesca hash table distribuita i cui valori sono B-tree ordinati. Un hash sulla sceglie un nodo di storage; un B-tree ordina gli item per sort key al suo interno. Ogni scrittura replica in modo sincrono su tre nodi in tre Availability Zone prima di confermare.
- La partition key viene hashata, non cercata. DynamoDB esegue una funzione di
hash sulla tua
PKper trovare l'unico nodo di storage che contiene quella partizione — un salto O(1), a prescindere dalla dimensione della tabella. - La sort key vive in un B-tree. Dentro una partizione, gli item sono
memorizzati in un B-tree ordinato lessicograficamente per
SK, ed è per questo che le letture per range (begins_with,between) sono economiche e loScanno. - Ogni scrittura colpisce tre nodi prima di confermare. Una scrittura va a un
leader, che replica in modo sincrono a due peer in altre AZ — la durabilità è
pagata prima che il tuo
PutItemritorni. - È per questo che esistono le regole degli access pattern. Hash-poi-albero è veloce solo quando leggi per chiave. Niente chiave, niente percorso veloce — ripieghi sulla scansione dell'albero.
Inizia dalla struttura dati, non dall'API
Venendo da SQL, immagini una tabella come righe su disco con un query planner che sceglie gli index. DynamoDB non ha planner. Il layout di storage è il contratto — cosa è veloce e cosa è un footgun cadono entrambi direttamente da due strutture.
Immagina una gigantesca mappa distribuita. La chiave è un hash della tua partition key. Il valore non è un singolo item — è un intero B-tree di item che condividono quella partition key, ordinati per sort key.
Tutto il resto — la semantica delle query, gli avvisi sui 10 GB, perché una chiave
mancante forza uno Scan — è una conseguenza di quell'unica frase.
Fai l'hash della partition key per trovare il nodo
Quando arriva una richiesta, DynamoDB applica una funzione di hash interna al valore della partition key. L'hash mappa in modo deterministico a un nodo di storage — la partizione fisica che possiede quegli item. AWS lo documenta come il meccanismo dietro le ricerche per chiave a tempo costante, a prescindere dalla dimensione della tabella.
Quello è il passo O(1). Una tabella da 10 TB e una da 10 KB costano lo stesso da localizzare: hash, salto, fatto. Non c'è scansione di index per trovare il nodo, niente statistiche, niente piano.
Il trucco è il rovescio della medaglia. Se non fornisci la partition key, DynamoDB
non ha alcun nodo a cui saltare — deve percorrere ogni partizione. Quello è uno
Scan, ed è la differenza tra O(1) e leggere l'intera tabella.
La richiesta fa l'hash su esattamente una partizione, poi discende il B-tree di sort key di quella partizione fino all'item — due passi economici invece di una scansione della tabella.
Ordina gli item in un B-tree per-partizione
Dentro una singola partizione, gli item non sono un heap. Sono tenuti in un
B-tree con chiave la sort key, ordinati lessicograficamente. Una ricerca in un
B-tree è O(log n), e cosa cruciale quell'n sono gli item in una partizione, non
l'intera tabella.
È l'intera ragione per cui le letture per range di sort key sono economiche. Prendi una tabella di telemetria di flotta dove le letture di ogni dispositivo vivono sotto un'unica partition key:
| PK | SK |
|---|---|
| PK = DEVICE#a91 | SK = READING#2026-06-23T08:00Z |
| PK = DEVICE#a91 | SK = READING#2026-06-23T08:05Z |
| PK = DEVICE#a91 | SK = READING#2026-06-23T08:10Z |
Poiché il B-tree è ordinato, "tutte le letture tra le 08:00 e le 09:00" è una discesa dell'albero fino al valore di partenza più una camminata sequenziale — non un filtro su ogni lettura che il dispositivo abbia mai inviato. Leggi solo il range corrispondente.
Quell'ordinamento è anche perché una query begins_with(SK, "READING#2026-06-23")
è veloce mentre filtrare su un attributo non-chiave non lo è. L'albero può fare il
seek per SK; non può fare il seek per nient'altro. Per comporre quelle condizioni
di chiave in sicurezza, costruiscile nell'Expression Builder per
DynamoDB invece di concatenare stringhe a mano:
KeyConditionExpression PK = :pk AND begins_with(SK, :day)
Replica ogni scrittura su tre AZ
Una partizione non è una sola macchina. Ognuna è replicata su tre nodi in tre Availability Zone — una discendenza di design che risale al modello di replica del paper Amazon Dynamo del 2007.
Un nodo è il leader per la partizione. Una scrittura va al leader, che scrive
localmente e replica ai suoi due peer. Il leader conferma la scrittura una volta che
un quorum durevole di nodi la possiede — così la durabilità tra le AZ è pagata
prima che il tuo PutItem ritorni.
Le letture hanno una scelta. Una lettura fortemente coerente va al leader e vede l'ultima scrittura committata. Una lettura eventualmente coerente può essere servita da uno qualsiasi dei tre nodi, uno dei quali può essere indietro di qualche millisecondo — è il ritardo che scambi per letture più economiche e più disponibili.
| Eventualmente coerente | Fortemente coerente | |
|---|---|---|
| Servita da | Uno dei 3 nodi | Solo il nodo leader |
| Vede l'ultima scrittura | Forse (piccolo ritardo) | Sempre |
| Costo RCU | Metà | Pieno |
| Disponibilità | Più alta | Più bassa (nodo singolo) |
La stessa idea di propagazione async è perché una lettura su un GSI può essere stantia — vedi i GSI sono eventualmente coerenti.
Leggi le regole dalla struttura
Quasi ogni "regola" di DynamoDB è solo fisica dello storage:
- Fornisci sempre la partition key. Niente chiave, niente bersaglio per l'hash — stai scansionando l'intera mappa. È il cuore di Query vs Scan.
- Co-localizza ciò che leggi insieme sotto un'unica partition key, così che un singolo hash + camminata dell'albero restituisca l'intera item collection. È la fondazione del single-table design.
- Mantieni le partizioni limitate. Una partizione è un B-tree su un insieme finito di nodi; una hot key fuori controllo o il tetto di 10 GB di un LSI sono entrambi limiti di quella partizione fisica.
Una volta che vedi la forma hash-poi-B-tree, la disciplina degli access pattern smette di sembrare arbitraria — stai solo tenendo ogni lettura sul percorso veloce.
Prossimi passi
Modella le tue chiavi per corrispondere alla struttura con strategie per le sort key e single-table design, poi assembla le espressioni effettive nell'Expression Builder per DynamoDB. Prova DynoTable per guardare queste letture eseguirsi sulle tue tabelle e vedere esattamente quali item una condizione di chiave riporta indietro.