Intermedio7 min di lettura

Denormalizzazione in DynamoDB

Venendo da SQL, la denormalizzazione sembra un peccato: dati duplicati, nessuno singolo fonte di verità. Nel DynamoDB il punto è tutto. Non ci sono join, quindi tu copia i dati correlati sull'articolo che ne ha bisogno e rileggili in un colpo solo.

Cos'è la denormalizzazione in DynamoDB?

La denormalizzazione in DynamoDB significa copiare i dati correlati sull'elemento che lo legge, quindi una singola query restituisce tutto in un colpo solo. Poiché DynamoDB non ha join, pre-join al momento della scrittura invece di unire le tabelle insieme al momento della lettura. Il compromesso è la vecchiaia: solo valori duplicati che cambiano raramente.

  • Nessun join significa pre-join al momento della scrittura. Memorizza il valore correlato nel file elemento che lo legge, quindi una query non necessita mai di una seconda ricerca.
  • Due versioni. Incorpora dati nidificati in un attributo complesso su un articolo oppure duplica un valore su più elementi.
  • Il footgun è stantio. Quando la fonte cambia, ogni copia è sbagliata finché non distribuisci l'aggiornamento. Solo valori duplicati che cambiano raramente.
  • Compra letture, non scritture. Scambia più scritture (e con maggiore attenzione). letture economiche a richiesta singola.

Perché non ci sono join su cui ricorrere

Un "JOIN" relazionale riassembla le righe normalizzate al momento della lettura. DynamoDB non ha join: un Query ne legge unoe restituisce esattamente ciò che è immagazzinato lì. Niente unisce due tabelle per te. (Sulla produzione leggi percorso, comunque - per l'audit ad hoc o il controllo della deriva, DynoTable's SQL Workbench esegue un vero JOIN su DynamoDB lato client.)

Quindi i dati devono già essere modellati per la lettura. Se uno schermo ha bisogno di un post e il nome del suo autore, quel nome deve vivere da qualche parte che il post letto già tocca. Il documento Amazon Dynamo del 2007 ha reso esplicito questo commercio: abbandonare le caratteristiche relazionali per ottenere letture prevedibili su larga scala: il trade DynamoDB ora offre come letture a una cifra al millisecondo.

Modello 1: incorpora con un attributo complesso

Gli attributi DynamoDB possono contenere mappe e liste annidate, non solo scalari. Quindi una forma comune di denormalizzazione è inserire un oggetto figlio direttamente al suo interno elemento genitore invece di dargli il proprio elemento.

Un post con i suoi tag e una piccola istantanea dell'autore, tutto su un unico elemento:

PKSKauthortags
POST#9f3META{id: U#12, name: "Mara Vance"}["dynamodb","aws"]

Un GetItem restituisce insieme il post, i tag e il blocco dell'autore. No seconda lettura. Questo è ottimo per i dati di proprietà del genitore e vincolati dimensione: una manciata di tag, un'istantanea dell'autore.

Un singolo elemento DynamoDB raggiunge il limite massimo di 400 KB, attributo nomi e valori inclusi (Quote di servizio). Incorpora un elenco illimitato (ogni commento su un post virale) e lo supererai.

Modello 2: duplica un valore tra gli elementi

Il caso del blog è quello dei libri di testo. Elenca i post e desideri che ogni riga mostri il file il nome visualizzato dell'autore, ma non vuoi che venga recuperato una seconda lettura per post.

Quindi scrivi il nome dell'autore su ciascun elemento del post quando il post viene creato:

PKSKauthorIdauthorNametitle
POST#9f3METAU#12"Mara Vance""Modeling 1:N"
POST#a71METAU#12"Mara Vance""Sparse GSIs"
POST#b04METAU#88"Lio Tan""Query vs Scan"

UNsui post (ad esempio GSI1PK = "POST", o uno digitato dall'autore) rende l'intero elenco - titolo e autore - senza ricerca per riga. begins_with sulla chiave di partizione non è un file cosa; un Query necessita dell'uguaglianza delle chiavi di partizione, quindi con le chiavi di partizione per post l'elenco arriva da GSI, non Query su POST#. Il nome dell'autore è denormalizzato: la copia canonica risiede su USER#12 e ogni post porta la propria copia.

Il commercio è proprio lì. Hai trasformato una lettura N+1 in una lettura, al costo di tenendo "Mara Vance"` in N+1 posti.

Incorpora o duplica: quale

Incorpora (attributo complesso)Duplica (copia tra elementi)
Formafiglio nidificato all'interno del genitorestesso valore su molti articoli
Ideale perdati limitati e di proprietà dei genitoriun valore condiviso che molti elementi mostrano
Leggiuno GetItemuno Query
Costo aggiornamentoriscrivi l'unico elemento genitoredistribuire a ventaglio ogni copia
Rischio dimensionaleLimite articolo 400 KBnessuno per articolo

Utilizza incorpora quando il bambino appare sempre e solo con il tuo genitore. Raggiungi duplicare quando molti elementi indipendenti devono mostrare lo stesso valore condiviso.

Il fucile: copie stantie

Mara si rinomina "Mara V." Aggiorna USER#12. Ogni articolo del post è ancora dice "Mara Vance" finché non li aggiusti.

Quindi l'aggiornamento di un valore duplicato è una scrittura fan-out, non una riga. Tu interroghi tutti gli elementi interessati e riscrivili ciascuno, idealmente protetti in modo da toccare solo le righe che mantengono ancora il vecchio valore:

UPDATE POST#9f3
SET authorName = "Mara V."
WHERE authorName = "Mara Vance"

Puoi comporre il condizionale SET contro authorName nel file Expression Builder e copia il file generato "UpdateExpression" e "ConditionExpression" direttamente nel tuo codice.

Il fan-out è una scrittura per articolo. Query la chiave GSI dell'autore per quell'autore post, quindi pubblicare gli aggiornamenti. La sequenza:

"DynamoDB"App"DynamoDB"App"Aggiorna nome USER"Query dei post dell'autore""POST"Aggiorna ogni authorName"

Ogni modifica alla fonte è una query più una scrittura per copia. In DynoTable il fan-out finisce nell'area di staging in primo luogo, come differenza rivedibile per attributo per articolo: vedi ogni copia che lo è sta per cambiare prima che venga spedito qualsiasi cosa.

Questo è il motivo per cui la regola è solo valori duplicati che cambiano raramente. Una visualizzazione nome, livello del piano, etichetta di categoria: va bene. Un contatore live o modificato di frequente campo: non farlo; il fan-out ti mangerà vivo.

Costo di scrittura fan-out

Ogni copia aggiornata costituisce una scrittura fatturata separatamente. In "us-east-1" su richiesta, l'aggiornamento di 50 articoli di post dopo la ridenominazione dell'autore costa 50 × WCU — in genere 1 WCU per KB per articolo quando ciascuna riga di post è ≤ 1 KB. Il lato letto rimane uno Query; il lato di scrittura varia in base al numero di duplicati mantenuti. Stima entrambi i percorsi nel calcolatore dei prezzi.

Quando la normalizzazione vince ancora

Se un valore cambia spesso o un elemento viene letto in modo veramente imprevedibile pattern, mantienilo normalizzato e accetta la lettura extra. La denormalizzazione è un ottimizzazione per modelli di accesso noti e con uso intensivo di lettura: non è un'impostazione predefinita da applicare ovunque. Partecipa preliminarmente alle letture che esegui effettivamente e lascia stare il resto.

Per decidere dove risiedono questi attributi duplicati, modella i modelli di accesso prima: vedere design a tabella singola e, per la lettura lato del commercio, Query vs Scan.

Scarica DynoTable per ispezionare una tabella denormalizzata, individuare quale copia sono andati alla deriva ed esegui l'aggiornamento fan-out rispetto ai tuoi dati. Suo SQL Workbench può anche "JOIN" la fonte della verità contro le copie per trovare la deriva in una query.

Aggiornato