Intermedio8 min di lettura

Relazioni uno-a-molti in DynamoDB

Un piano di controllo SaaS ha quasi sempre una gerarchia di contenimento: uno spazio di lavoro possiede molti progetti. In SQL inseriresti una chiave esterna workspace_id sul file tabella dei progetti e "JOIN".

DynamoDB non ha join né chiavi esterne, quindi la relazione deve vivere nel file schema chiave stesso. Fatto bene, "carica uno spazio di lavoro e ogni progetto al suo interno" diventa un singolo Query invece di una lettura più una scansione di follow-up.

Come si modella una relazione uno-a-molti in DynamoDB?

Date lo stesso al genitore e a tutti i suoi figliquindi ne condividono uno, quindi differenziarli con la chiave di ordinamento. DynamoDB non ha join o chiavi esterne, quindi la relazione risiede nello schema di chiavi stesso. Il caricamento di un genitore più ogni figlio diventa quindi un singolo Query invece di un join.

  • Modella le letture, non le entità. Esiste solo la relazione uno-a-molti per servire "elenca i progetti di uno spazio di lavoro": modella le chiavi attorno a quella query.
  • Codifica il genitore in quello del figlio. Dare lo spazio di lavoro e tutto il resto proietta lo stesso valore della chiave di partizione in modo che arrivino in uno .
  • Quindi la lista letta è una Query. Ritornano il genitore più i suoi figli insieme: nessuna unione, nessun secondo round trip (un Query restituisce fino a 1 MB per pagina, impaginazione tramite "LastEvaluatedKey" oltre).
  • Guarda il. Un enorme inquilino concentra tutto il tuo traffico su uno solo partizione; uno spazio di lavoro gigantesco potrebbe aver bisogno di una chiave frammentata e di una lettura a ventaglio.

Innanzitutto il modello di accesso

La modellazione DynamoDB è basata innanzitutto sul modello di accesso, non sull'entità: la stessa disciplina dietro design a tabella singola. Prima di sceglierne uno qualsiasi chiave, annota le letture effettivamente emesse dall'app:

  • Ottieni le impostazioni di uno spazio di lavoro.
  • Elenca tutti i progetti in uno spazio di lavoro, iniziando dal più recente.
  • Ottieni un progetto specifico per ID.

La relazione "uno spazio di lavoro, molti progetti" è importante solo a causa della lettura n. 2. Se non avessi mai bisogno di elencare insieme i progetti di uno spazio di lavoro, non faresti il modello la relazione in generale: memorizzeresti i progetti in modo indipendente.

Quindi la domanda non è mai "come rappresento uno-a-molti?" in astratto. Lo è "quali domande deve servire questa relazione?" Rispondi, quindi modella le chiavi attorno ad esso.

Perché una chiave esterna non aiuta in questo caso

In DynamoDB ogni GetItem e Query ha come target una chiave di partizione, e la Il servizio esegue l'hashing di quella chiave per individuare la partizione che contiene l'elemento.

AWS lo dice direttamente nei Componenti principali docs: il valore della chiave di partizione è l'input per una funzione hash interna che decide dove risiedono i dati.

Questo posizionamento basato su hash è l'eredità dell'originale Dynamo del 2007: Carta Store di valore-chiave altamente disponibile di Amazon, in cui hashing coerente distribuisce le chiavi tra i nodi.

Un semplice attributo workspace_id su un elemento del progetto è invisibile a questo macchinario - DynamoDB non può "seguirlo".

Per recuperare elementi correlati in una richiesta, è necessario codificare l'identità del genitore la chiave di partizione del progetto, in modo che tutti gli elementi di uno spazio di lavoro abbiano lo stesso hash partizione e un Query può spazzarli.

Esempio realizzato: spazi di lavoro e progetti

Utilizzare uno schema di chiavi generico e sovraccaricato. Chiama la chiave di partizione "EntityRef" e il file chiave di ordinamento "Dettaglio". L'identità dello spazio di lavoro va in "EntityRef" per entrambi i file elemento dell'area di lavoro e ogni progetto sotto di esso:

EntityRefDetailattributes
WS#acmeMETAdisplayName, region, seatLimit
WS#acmePROJ#2026-0007title, status, createdBy
WS#acmePROJ#2026-0042title, status, createdBy
WS#acmePROJ#2026-0118title, status, createdBy
WS#globexMETAdisplayName, region, seatLimit
WS#globexPROJ#2026-0009title, status, createdBy

Lo spazio di lavoro e tutti i suoi progetti condividono EntityRef = "WS#acme", quindi formano un file singola collezione di oggetti che convivono su un unico divisorio.

La chiave di ordinamento "Detail" li separa: "META" è il record dell'area di lavoro e ciascuno project porta un prefisso "PROJ#" con un ID ordinato in base al tempo con riempimento zero, quindi progetti ordinare in modo naturale.

Visivamente, il genitore e i suoi figli si impilano all'interno di una partizione, ordinata da chiave di ordinamento:

Partizione: EntityRef = WS#acmeMETA impostazioni workspacePROJ#2026-0007PROJ#2026-0042PROJ#2026-0118

Un Query su EntityRef = "WS#acme" spazza l'intero stack: genitore più ogni bambino - in una sola lettura.

Ora i tre modelli di accesso si riducono ciascuno a una chiamata:

  • Impostazioni dell'area di lavoroGetItem(EntityRef="WS#acme", Detail="META").
  • Elenca progetti dal più recente al primoQuery(EntityRef="WS#acme") con Dettaglio begins_with "PROJ#", eseguito in ordine decrescente (ScanIndiceAvanti = false).
  • Un progettoGetItem(EntityRef="WS#acme", Detail="PROJ#2026-0042").

Il secondo è il punto. Il genitore e i suoi figli tornano da uno Query, nessun join e nessun secondo andata e ritorno — DynamoDB restituisce fino a 1 MB per pagina e ti fornisce un LastEvaluatedKey per recuperare il resto. Questa è la mossa non puoi farlo con un attributo di chiave esterna e un Scan.

Scrivere a mano la condizione begins_with è complicato: la condizione chiave e morsi della sintassi di proiezione-espressione.

Il DynamoDB Expression Builder genera le mappe segnaposto KeyConditionExpression, #name/:value e un Snippet SDK pronto per l'esecuzione in modo da non combattere la grammatica:

KeyConditionExpression     "#er = :er AND begins_with(#d, :p)"
ExpressionAttributeNames   { "#er": "EntityRef", "#d": "Detail" }
ExpressionAttributeValues  { ":er": "WS#acme", ":p": "PROJ#" }

Esamina la raccolta di oggetti in DynoTable

Ogni riga che condivide un "EntityRef" è il file spazio di lavoro più i suoi figli, seduti uno accanto all'altro.

DynoTable li raggruppa in modo da vedere la relazione uno-a-molti come una contigua bloccare invece di indovinarlo su tabelle separate.

L'elemento META dell'area di lavoro e i suoi figli PROJ# raggruppati come un'unica raccolta di elementi nella vista tabella di DynoTable.
L'elemento META dell'area di lavoro e i suoi figli PROJ# raggruppati come un'unica raccolta di elementi nella vista tabella di DynoTable.

Le insidie e la forma alternativa

Alcune cose da guardare:

  • Partizioni attive. Ogni elemento di uno spazio di lavoro risiede su una partizione, quindi a un singolo inquilino molto grande o molto occupato concentra il traffico. Il capacità adattiva comportamento AWS descrive assorbe un'inclinazione moderata, ma uno spazio di lavoro con milioni di i progetti potrebbero richiedere una chiave frammentata (ad esempio WS#acme#01 … #10) e una lettura fan-out.
  • Dimensione della raccolta di elementi. Con un indice secondario locale, una singola partizione la raccolta di elementi è limitata a 10 GB; senza un LSI non esiste tale limite. Se stai valutando i tipi di indice qui, vedi GSI vs LSI.
  • Raggiungi Query, mai Scan. L'intero design esiste in modo che tu possa Query una partizione. Ritornando a un Scan filtrato per "trovare uno spazio di lavoro progetti" getta via il modello e legge l'intera tabella: la trappola è coperta in Query vs Scan.

Se hai davvero bisogno di elencare i progetti tra gli spazi di lavoro (ad esempio, all status = ACTIVE progetti a livello globale), la tabella di base non può rispondere: è la chiave di partizione ha ambito nell'area di lavoro.

Questo è un lavoro per un indice secondario che ripartiziona i progetti su un altro attributo, non per rimodellare questa relazione.

Passaggi successivi

Modella i modelli di accesso, codifica il genitore nella chiave di partizione del figlio e la lettura uno-a-molti è un singolo Query. Costruisci e convalida la condizione chiave con DynamoDB Expression Builder — e se preferisci iniziare dai modelli di accesso stessi, il free Strumento di progettazione a tabella singola disegna il Piano PK/SK/GSI con elementi di esempio.

Quindi download DynoTable per caricare questo schema, sfoglia il file workspace→proietta la raccolta di elementi in tempo reale e conferma che ogni query ne esegue esattamente una leggere. Se preferisci vedere gli spazi di lavoro e i progetti come una visione congiunta e relazionale, DynoTable's SQL Workbench esegue anche quel JOIN.

Aggiornato

Prova questo design in modo interattivo

Abbozza le tue entità e i tuoi pattern di accesso nello strumento gratuito di single-table design per DynamoDB — suggerisce template di chiavi PK/SK, mostra un'anteprima delle collezioni di item e indica quali pattern hanno bisogno di un GSI.

Apri lo strumento di single-table design