Single-table design in DynamoDB
Venendo da SQL, l'istinto è una tabella per entità: customers, orders,
order_items. In DynamoDB quell'istinto è di solito sbagliato. Una singola tabella che
memorizza ogni entità, distinta da prefissi di chiave sovraccaricati, ti permette di recuperare
un genitore e i suoi figli in una sola Query — niente join, niente N+1.
Parti dai pattern di accesso, non dalle entità
Il single-table design è access-pattern-first. Prima di scegliere una singola chiave,
annota ogni lettura che la tua app fa — "ottieni il profilo di un cliente", "elenca gli
ordini di un cliente dal più recente", "trova tutti gli ordini aperti" — perché le chiavi esistono
solo per servire quell'elenco. La normalizzazione relazionale ottimizza l'archiviazione; la modellazione
DynamoDB ottimizza le query che già sai di dover eseguire. Enumerale, poi
progetta le chiavi perché ognuna sia una singola Query.
L'idea
Scegli nomi di chiave generici (PK, SK) e codifica il tipo di entità nel valore:
| PK | SK | attributes |
|---|---|---|
| CUSTOMER#42 | PROFILE | name, email, plan |
| CUSTOMER#42 | ORDER#2026-001 | total, status |
| CUSTOMER#42 | ORDER#2026-002 | total, status |
Ora una Query PK = "CUSTOMER#42" restituisce il profilo e ogni ordine in una
singola lettura fatturata. SK begins_with "ORDER#" la restringe ai soli ordini.
Visivamente, gli Item sovraccaricati si impilano sotto un'unica partition key come una singola collezione di Item:
Una sola lettura della partizione restituisce il cliente e ogni ordine insieme.
GSI sovraccaricati
Lo stesso trucco funziona sugli indici. Metti un GSI1PK/GSI1SK generico sugli Item, e un
singolo GSI serve più pattern di accesso a seconda di cosa ogni Item scrive
in quegli attributi:
| PK | SK | GSI1PK | GSI1SK |
|---|---|---|---|
| ORDER#001 | METADATA | STATUS#OPEN | 2026-01-04 |
| ORDER#002 | METADATA | STATUS#OPEN | 2026-01-05 |
Ora Query GSI1 WHERE GSI1PK = "STATUS#OPEN" elenca gli ordini aperti per data — un
pattern a cui la tabella di base non può rispondere. Un'entità diversa può riutilizzare GSI1 con il proprio
significato (es. CATEGORY#books). Un indice, molte query.
Molti-a-molti: la lista di adiacenza
Per le relazioni (un utente in molti team, un team con molti utenti), scrivi l'arco
due volte con gli id scambiati: PK=USER#1, SK=TEAM#9 e PK=TEAM#9, SK=USER#1.
Interrogare un lato elenca l'altro — il sostituto DynamoDB di una join table.
Quando non fare single-table
Non è gratis. Una tabella sovraccaricata è più difficile da ragionare, più difficile da evolvere e ostile all'analisi. Se i tuoi pattern di accesso sono davvero sconosciuti o cambiano costantemente, o i dati sono per lo più analitici, tabelle separate (o uno store diverso) possono essere la scelta più saggia. Il single-table vince quando i pattern sono noti e ad alto volume.
Costo della forma sbagliata
Modellare come tabelle separate forza uno Scan o un join lato client per ricomporre un
cliente, e questo è il trabocchetto dello Scan. Modella prima i pattern
di accesso, poi progetta le chiavi perché ognuno sia una Query.
Stima quanto costano questi Item per lettura con il calcolatore di dimensione e capacità degli Item, e prova DynoTable per sfogliare uno schema single-table e vedere le collezioni sovraccaricate affiancate.