Relazioni molti-a-molti in DynamoDB
Uno studente si iscrive a molti corsi; un corso può contenere molti studenti. In SQL raggiungi per una tabella di join e un "JOIN" a tre tabelle.
DynamoDB non ha join, quindi la relazione deve vivere nelle chiavi — e il
il trucco è memorizzare ciascun fronte di registrazione in una forma in cui entrambe le parti possano Query
direttamente.
Questa guida accompagna gli studenti ↔ al problema dei corsi dall'inizio alla fine: i modelli di accesso, il
pattern che li risolve, uno schema chiave originale che puoi copiare e come leggere entrambe le direzioni senza mai scansionare la tabella.
Come si modella una relazione molti-a-molti in DynamoDB?
DynamoDB non ha join, quindi modelli una relazione molti-a-molti conmodello: memorizza ogni collegamento come un proprio elemento di bordo con chiave da un lato, quindi aggiungi un GSI invertito che scambia le chiavi. Un singolo bordo, scritto una volta, risponde quindi alle domande da entrambe le direzioni in modo economico.
- Memorizza ogni registrazione come elemento marginale, non come attributo di elenco su entrambi i lati.
- Inserisci il bordo dello studente (
PK = STU#…,SK = ENROLL#CRS#…) quindi unoQueryrestituisce l'intero elenco dei corsi di uno studente. - Aggiungi un invertito che scambia i ruoli (
GSI1PK = CRS#…) quindi lo stesso bordo risponde anche "chi c'è in questo corso?". - Un bordo, scritto una volta, si legge in modo economico in entrambe le direzioni: questo è l'intero gioco.
Inquadra prima i modelli di accesso
La modellazione DynamoDB è basata innanzitutto sul modello di accesso: sei tu a decidere le letture prima di scegliere un nome dell'attributo singolo. Una relazione molti-a-molti ha quasi sempre due simmetrici legge più le ricerche di entità:
- Ottieni il profilo di uno studente ed elenca tutti i corsi a cui è iscritto.
- Ottieni i metadati di un corso e elenca tutti gli studenti iscritti a quel corso.
- Cerca un singolo vantaggio di iscrizione: per aggiornare un voto o abbandonare il corso.
Le due letture dell'elenco puntano in direzioni opposte attraverso lo stesso insieme di
bordi. Un design ingenuo serve uno a buon mercato e forza un Scan per l'altro: l'esatto
fucile coperto in Query vs Scan.
Il compito è rendere entrambe le direzioni un singolo Query.
Utilizza il modello elenco di adiacenze
La guida di DynamoDB per le relazioni è la lista di adiacenze: modella ciascuna relazione come un elemento la cui chiave di partizione è un endpoint e la cui chiave di ordinamento è il altro.
AWS lo documenta sul Best practice per la gestione delle relazioni molti-a-molti pagina della Guida per sviluppatori DynamoDB.
Perché le chiavi e non un secondo tabella? Perché la primitiva che ti dà DynamoDB è un Query
contro una singola partizione.
Un Query legge un intervallo contiguo di valori di chiavi di ordinamento sotto una chiave di partizione in uno
operazione fatturata: questo è l'unico "join" offerto dal motore.
Per ottenere una relazione che si legga in modo semplice da entrambi i lati, duplichi il bordo: scriverlo una volta digitato dallo studente, quindi utilizzare un indice secondario per proiettare lo stesso bordo incentrato sul corso.
Questo è il pensiero in chiave sovraccarica da Progettazione a tabella singola, applicato invece a una relazione di una gerarchia genitore-figlio.
La forma è rappresentata da due viste impilate dello stesso bordo: la tabella di base impostata dallo studente, il invertito GSI digitato per corso:
Ogni bordo viene scritto una volta sulla tavola base e proiettato nel GSI con le sue chiavi
scambiato, quindi un Query contro una delle partizioni legge la relazione in modo economico.
Il lignaggio risale all'Amazzonia del 2007 Documento Dynamo: la chiave di partizione è l'unità di distribuzione e l'accesso con chiave singola è il percorso rapido.
Le relazioni in DynamoDB sono un esercizio per piegare le letture molti-a-molti in modo così veloce percorso.
Fai l'esempio: studenti ↔ corsi
Utilizza una tabella con chiavi generiche, PK e SK, e codifica il tipo di entità nel
valore. Il bordo di registrazione ne è il cuore:
| PK | SK | attributes |
|---|---|---|
| STU#a91 | PROFILE | name, year, major |
| STU#a91 | ENROLL#CRS#math204 enrolledOn, grade | |
| STU#a91 | ENROLL#CRS#cs101 | enrolledOn, grade |
| CRS#math204 | METADATA | title, credits, term |
| CRS#cs101 | METADATA | title, credits, term |
Un singolo Query PK = "STU#a91" restituisce il profilo dello studente e ogni iscrizione
in una lettura. Restringilo con SK begins_with "ENROLL#" per ottenere solo i bordi del percorso.
Questo risolve "elencare i corsi di uno studente".
Ma "elenca gli studenti di un corso" punta nella direzione opposta e la tabella di base non può rispondere it, perché l'ID studente è nella chiave di partizione, non nella chiave di ordinamento.
Aggiungi un indice secondario globale invertito che scambia i ruoli. Dai agli elementi bordo a
coppia generica GSI1PK/GSI1SK che tiene il corso dal lato partizione e lo studente
dal lato dell'ordinamento:
| PK | SK | GSI1PK | GSI1SK |
|---|---|---|---|
| STU#a91 | ENROLL#CRS#math204 | CRS#math204 | STU#a91 |
| STU#b30 | ENROLL#CRS#math204 | CRS#math204 | STU#b30 |
| STU#a91 | ENROLL#CRS#cs101 | CRS#cs101 | STU#a91 |
Ora Query GSI1 WHERE GSI1PK = "CRS#math204" elenca tutti gli studenti di quel corso: il
leggere la tabella di base non potrebbe servire. Un elemento limite, scritto una volta, risponde a entrambi
direzioni.
Deve essere un GSI, non un LSI: la partizione del percorso è completamente diversa da quella partizione studente e un LSI condivide la chiave di partizione della tabella di base.
L'indice si estende su più partizioni, quindi deve essere globale: vedi GSI vs LSI.
GSI in DynamoDB vengono popolati in modo asincrono. Una nuova registrazione può richiedere a
momento in modo che appaia nella direzione CRS#….
Trattare l'elenco dei corsi letto come- che la Guida per gli sviluppatori chiama esplicitamente per gli indici secondari globali.
Scrivilo e leggilo in DynoTable
Scrivere la registrazione significa impostare quattro attributi chiave più i dati propri dell'edge. Il
La condizione che impedisce ad uno studente di iscriversi due volte allo stesso corso è una
attribute_not_exists(PK) protegge la chiave composita.
Questo è esattamente il tipo di condizione che puoi assemblare visivamente con DynamoDB Expression Builder invece di scrivendo a mano "ExpressionAttributeNames" e i valori segnaposto.
In DynoTable punti un Query su GSI1, imposta GSI1PK = "CRS#math204" e il
roster ritorna come una tabella che puoi leggere, ordinare e modificare sul posto, in entrambe le direzioni
la relazione esplorabile da uno schema.

Insidie e passaggi successivi
- Non memorizzare un lato come attributo di elenco. Un array
courseIdssull'elemento studente sembra ordinato finché un corso non ha bisogno del suo elenco, l'array raggiunge il limite massimo di 400 KB o due iscrizioni gareggiano e si scontrano a vicenda. Gli elementi Edge discreti vengono ridimensionati e aggiornati in modo indipendente. - Mantieni i dati edge sull'edge. Il "grado" e l'"enrolledOn" dell'iscrizione appartengono a l'elemento bordo, non duplicato sullo studente o sul corso: c'è esattamente una riga per (studente, corso) coppia da aggiornare.
- Propagazione Mind GSI. La direzione dell'indice invertito è eventualmente coerente, quindi a letto immediatamente dopo la registrazione potrebbe subire un ritardo di una frazione di secondo.
- Proietta solo ciò di cui ha bisogno il roster. Una proiezione
KEYS_ONLYo ristretta mantiene GSI piccolo quando la visualizzazione dell'elenco necessita solo di ID.
Per approfondire i modelli circostanti, leggi Design a tabella singola per chiavi sovraccaricate e GSI vs LSI per quando l'indice invertito deve essere globale. E a partire dalle proprie relazioni, quelle libere Strumento di progettazione a tabella singola trasforma un elenco dei modelli di accesso come "elenca i corsi di uno studente / elenca gli studenti di un corso" in un piano PK/SK/GSI con elementi di esempio.
Quindi scarica DynoTable per modellare realmente lo schema degli studenti ↔ dei corsi —
scrivi i bordi, costruisci la condizione con Expression Builder ed interroga entrambi
direzioni della relazione senza una sola scansione. E quando vuoi il
comunque la classica visualizzazione JOIN a tre tabelle, SQL di DynoTable
Workbench lo esegue sui tuoi tabelle live.


