Intermedio7 min di lettura

Quando NON Usare il Single-Table Design in DynamoDB

Il single-table design è il consiglio di default per DynamoDB, e se lo merita: una Query restituisce un genitore e i suoi figli, niente join, niente N+1.

Ma è uno scambio — compri velocità di lettura con uno schema rigido e opaco. Alcuni carichi di lavoro non possono permettersi quel prezzo, e forzare una tabella su di essi è un footgun a sé.

Quando non dovresti usare il single-table design in DynamoDB?

Evita il single-table design quando il tuo carico di lavoro è incentrato su analytics OLAP pesanti, CRUD semplice su un pugno di entità non correlate, o entità che scalano e falliscono in modo indipendente. In questi casi più tabelle si leggono meglio, costano uguale e restano flessibili. Il single-table design vince solo quando i pattern di accesso sono noti, correlati e ad alto volume.

  • Analytics pesanti? Non fare single-table. Le chiavi sovraccaricate sono ostili all'OLAP — esporta in uno store colonnare e interroga lì.
  • CRUD semplice con una manciata di pattern di accesso? Una tabella per entità va bene, è leggibile, e non ti costa nulla in performance.
  • Entità che scalano o falliscono indipendentemente? Tabelle separate ti permettono di tunare, fatturare e isolare il raggio d'esplosione per ognuna.
  • Il single-table vince ancora quando i tuoi pattern sono noti, correlati e ad alto volume — è il caso per cui è stato costruito.

Sappi cosa costa davvero il single-table

Il single-table design non è gratis; sposta solo il costo fuori dal percorso di lettura e su tutto il resto. Paghi in leggibilità e flessibilità.

Una tabella che contiene cinque tipi di entità dietro PK/SK è difficile da leggere, difficile da fare onboarding, e difficile da cambiare. Un nuovo pattern di accesso può significare un backfill su ogni tipo di Item nella partizione.

Quindi la domanda non è "il single-table è buono?". È "i miei pattern di accesso giustificano la rigidità?". Quando non lo fanno, reggiungi a più tabelle.

Non fare single-table su un carico di lavoro analytics

DynamoDB è costruito per OLTP — letture piccole, note, point-and-range. Le analytics sono OLAP: GROUP BY, grandi aggregati, slicing ad-hoc su tutto il dataset. Le due tirano in direzioni opposte.

Il single-table design peggiora l'OLAP, non lo migliora. Chiavi sovraccaricate e tipi di entità misti significano che un job di analytics deve prima districare quale Item è quale prima di poter sommare qualcosa — l'opposto di una scan colonnare pulita.

Venendo da SQL, il riflesso è scrivere l'aggregato sulla tabella live. In DynamoDB quello è uno Scan completo — paghi e leggi ogni Item, che è il footgun dello Scan a pieno volume.

La soluzione non è una chiave più ingegnosa. È uno store diverso. L'indicazione di AWS stessa è esportare DynamoDB su S3 ed eseguire le analytics con un query engine come Athena.

Tieni OLTP e OLAP su engine separati (AWS DynamoDB Developer Guide, S3DataExport.html).

Non fare single-table su CRUD semplice

Se la tua app legge e scrive poche entità non correlate per il loro id, e hai forse tre pattern di accesso, il single-table non ti compra nulla.

Prendi una tabella Tenants e una tabella ApiKeys per un piccolo tool B2B:

Tenants
TenantIdNamePlanTier
TNT-8842Northwindpro
ApiKeys
KeyIdTenantIdScope
KEY-01H9...TNT-8842read-write

Ogni query è un GetItem per id, o una Query su un GSI con chiave su TenantId. Non c'è alcun fetch genitore-e-figli da ottimizzare, quindi non c'è nulla che una partizione sovraccaricata possa vincere. Due tabelle chiare si leggono meglio di una torbida.

La trappola è il cargo-culting del single-table perché è "best practice". La best practice è access-pattern-first. Se i pattern sono banali, la forma semplice è la forma giusta.

Dividi le tabelle che scalano o falliscono indipendentemente

Una singola tabella condivide una superficie di throughput, un backup, un raggio d'esplosione. Quando due entità hanno tassi di scrittura o esigenze di durabilità molto diversi, quel destino condiviso diventa una passività.

Immagina un sistema di tracciamento flotta. I veicoli cambiano raramente; la loro telemetria si riversa ogni secondo:

Vehicles (freddo, basso tasso di scrittura)
VehicleIdMakeModelRegion
VEH-204VolvoFH16eu-west
Telemetry (caldo, alto tasso di scrittura, con TTL)
DeviceTsVehicleIdSpeedKphFuel
2026-06-23T10:00:01ZVEH-204880.61

Due tabelle ti permettono di provisionare la telemetria per un firehose, tenere i veicoli piccoli e economici, impostare un TTL solo sulla telemetria, e impedire a una tempesta di scritture di telemetria di mettere in throttling le letture del catalogo veicoli. Una sola tabella accoppia tutto questo.

Secondo il paper Amazon Dynamo del 2007, partizionamento e disponibilità sono preoccupazioni di prima classe — tabelle indipendenti ti danno controllo indipendente su entrambi.

Mappa la decisione prima di impegnarti

Fai passare il carico di lavoro attraverso un gate: le entità sono correlate, e i pattern sono noti e ad alto volume? Se no, più tabelle.

Ecco la scelta come flusso — parti dall'alto e segui il primo ramo che corrisponde:

NoNoNoNuovo carico di lavoroAnalytics pesantio OLAP?Store separato(export + Athena)Entità correlate+ recuperate insieme?Più tabelle(CRUD semplice)Pattern noti,ad altovolume?Più tabelle(resta flessibile)Single-tabledesign

Solo la foglia in basso a destra merita il single-table; ogni altro percorso è servito meglio da più di una tabella.

Singola vs multiple, testa a testa

FattoreSingle-tableTabelle multiple
Letture correlateUna Query, niente joinJoin client-side o round-trip extra
LeggibilitàChiavi sovraccaricate opacheUna entità per tabella, auto-documentante
Nuovo pattern di accessoSpesso un backfillAggiungi una tabella o un GSI in isolamento
Analytics / OLAPOstile — districa prima di aggregareEsporti comunque, ma più pulito per entità
Scaling indipendenteThroughput + raggio d'esplosione condivisiTuna, fattura, TTL e fai backup separatamente
Migliore quandoPattern noti, correlati, ad alto volumeNon correlati, in evoluzione o analitici

Errori + prossimi passi

L'errore speculare è la sovra-correzione — dividere entità genuinamente correlate e ad alto volume in una tabella-per-entità e ricostruire join in stile SQL nella tua app. È la trappola N+1 che il single-table elimina.

Scegli la forma che i pattern di accesso chiedono, non il dogma.

Quando modelli relazioni, appoggiati al tipo di indice giusto — vedi GSI vs LSI prima di aggiungerne uno.

Quando scrivi una query su uno schema multi-tabella, abbozza la KeyConditionExpression prima nel DynamoDB Expression Builder.

Così cogli una forma a Scan completo prima che arrivi in produzione.

Poi prova DynoTable per navigare entrambe le forme sulle tue tabelle e vedere quale i tuoi pattern di accesso vogliono davvero.

Aggiornato