Intermediário7 min de leitura

Desnormalização em DynamoDB

Vindo de SQL, a desnormalização parece um pecado – dados duplicados, nenhum fonte da verdade. Em DynamoDB esse é o ponto principal. Não há junções, então você copie os dados relacionados no item que precisa deles e leia-os de uma só vez.

O que é desnormalização em DynamoDB?

A desnormalização em DynamoDB significa copiar os dados relacionados no item que os lê, de modo que uma única consulta retorna tudo de uma só vez. Como DynamoDB não tem junções, você pré-junta no momento da gravação em vez de unir as tabelas no momento da leitura. A desvantagem é a desatualização – apenas valores duplicados que raramente mudam.

  • Sem junções significa que você pré-ingressa no momento da gravação. Armazene o valor relacionado no item que o lê, portanto, uma consulta nunca precisa de uma segunda pesquisa.
  • Dois tipos. Incorporar dados aninhados em um atributo complexo em um item ou duplicar um valor em muitos itens.
  • A arma está obsoleta. Quando a fonte muda, todas as cópias estão erradas até você espalhar a atualização. Apenas valores duplicados que raramente mudam.
  • Ele compra leituras, não gravações. Você troca mais (e com mais cuidado) gravações por leituras baratas e de solicitação única.

Por que não há junções para recorrer

Um JOIN relacional remonta as linhas normalizadas no momento da leitura. DynamoDB não tem join — um Query lê ume devolve exatamente o que está armazenado lá. Nada une duas mesas para você. (Na produção, leia caminho, de qualquer maneira - para a auditoria ad-hoc ou verificação de desvio, SQL de DynoTable Workbench executa um JOIN real no lado do cliente DynamoDB.)

Portanto, os dados já devem estar moldados para a leitura. Se uma tela precisa de uma postagem e o nome do autor, esse nome deve estar em algum lugar que a postagem lida já toque. O artigo do Amazon Dynamo de 2007 tornou esse comércio explícito: abandone os recursos relacionais para obter leituras previsíveis em escala - a negociação DynamoDB agora entrega como leituras de milissegundos de um dígito.

Padrão 1 — incorporar com um atributo complexo

Os atributos DynamoDB podem conter mapas e listas aninhados, não apenas escalares. Então uma forma comum de desnormalização é colocar um objeto filho diretamente dentro de seu item pai em vez de fornecer seu próprio item.

Uma postagem com suas tags e um pequeno instantâneo do autor, tudo em um item:

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

Um GetItem retorna a postagem, as tags e o bloco do autor juntos. Não segunda leitura. Isso é ótimo para dados que pertencem ao pai e estão limitados tamanho – um punhado de tags, um instantâneo do autor.

Um único item DynamoDB atinge o máximo de 400 KB, atributo nomes e valores incluídos (Cotas de serviço). Incorpore uma lista ilimitada (cada comentário em uma postagem viral) e você a superará.

Padrão 2 – duplicar um valor entre itens

O caso do blog é o do livro didático. Você lista postagens e deseja que cada linha mostre o nome de exibição do autor — mas você não quer uma segunda leitura por postagem para buscá-lo.

Então você escreve o nome do autor em cada item da postagem quando a postagem é criada:

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

UMsobre postagens (digamos GSI1PK = "POST", ou uma digitada pelo autor) renderiza o todo lista — título e autor — sem pesquisa por linha. begins_with na chave de partição não é um coisa; um Query precisa de igualdade de chave de partição, então com chaves de partição por postagem a lista vem do GSI, não um Query sobre POST#. O nome do autor é desnormalizado: a cópia canônica reside em USER#12, e cada postagem carrega sua própria cópia.

O comércio está aí. Você transformou uma leitura N+1 em uma leitura, ao custo de segurando "Mara Vance" em N+1 lugares.

Incorporar vs. duplicar — qual

Incorporar (atributo complexo)Duplicar (copiar entre itens)
Formafilho aninhado dentro do paimesmo valor em muitos itens
Melhor paradados limitados e de propriedade dos paisum valor compartilhado que muitos itens exibem
Leiaum GetItemum Query
Custo de atualizaçãoreescrever o item paidistribua cada cópia
Risco de tamanhoLimite de item de 400 KBnenhum por item

Use incorporar quando o filho só aparecer com o pai. Alcançar duplicado quando muitos itens independentes precisam mostrar o mesmo valor compartilhado.

A arma de fogo: cópias obsoletas

Mara renomeia-se para "Mara V." Você atualiza USER#12. Cada item de postagem ainda diz "Mara Vance" até você ir consertá-los.

Portanto, atualizar um valor duplicado é uma gravação de fan-out, não uma linha única. Você consulta cada item afetado e reescrever cada um - de preferência protegido para que você toque apenas nas linhas que ainda mantêm o valor antigo:

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

Você pode compor aquele SET condicional contra authorName no Expression Builder e copie o arquivo gerado UpdateExpression e ConditionExpression direto no seu código.

Fan-out é uma gravação por item. Query o GSI digitado pelo autor para esse autor postagens e, em seguida, emita as atualizações. A sequência:

"DynamoDB"App"DynamoDB"App"Atualizar nome de USER"Query dos posts do autor""POST"Atualizar cada authorName"

Cada alteração na fonte é uma consulta mais uma gravação por cópia. Em DynoTable o fan-out chega à área de teste primeiro, como uma comparação revisável por atributo por item - você vê cada cópia que é prestes a mudar antes que qualquer coisa seja enviada.

É por isso que a regra é apenas valores duplicados que raramente mudam. Uma exibição nome, um nível de plano, um rótulo de categoria – tudo bem. Um contador ao vivo ou editado com frequência campo - não; o fan-out vai te comer vivo.

Custo de gravação de distribuição

Cada cópia atualizada é uma gravação faturada separada. Em us-east-1 sob demanda, atualizar 50 itens de postagem após a renomeação de um autor custa 50 × WCU - normalmente 1 WCU por KB por item quando cada linha de postagem for ≤ 1 KB. O lado lido permanece um Query; o lado da gravação é dimensionado de acordo com quantas duplicatas você mantém. Estimativa ambos os caminhos na calculadora de preços.

Quando a normalização ainda vence

Se um valor muda frequentemente ou um item é lido por pessoas genuinamente imprevisíveis padrões, mantenha-o normalizado e aceite a leitura extra. A desnormalização é um otimização para padrões de acesso conhecidos e com muita leitura — não é um padrão a ser aplicado em todos os lugares. Junte-se previamente às leituras que você realmente executa e deixe o resto em paz.

Para decidir onde esses atributos duplicados residem, modele os padrões de acesso primeiro - consulte design de tabela única e, para leitura lado da negociação, Query vs Scan.

Baixar DynoTable para inspecionar uma tabela desnormalizada, identificar quais cópias foram desviados e execute a atualização de distribuição em seus próprios dados. É SQL Workbench pode até JOIN a fonte da verdade contra as cópias para encontrar o desvio em uma consulta.

Atualizado