Intermediário8 min de leitura

Relacionamentos um-para-muitos em DynamoDB

Um plano de controle SaaS quase sempre tem uma hierarquia de contenção: um espaço de trabalho possui muitos projetos. Em SQL você colocaria uma chave estrangeira workspace_id no tabela de projetos e JOIN.

DynamoDB não tem junções nem chaves estrangeiras, então o relacionamento tem que viver no esquema chave em si. Feito corretamente, "carregue um espaço de trabalho e todos os projetos dentro dele" torna-se um único Query em vez de uma leitura mais uma varredura de acompanhamento.

Como você modela um relacionamento um-para-muitos em DynamoDB?

Dê aos pais e a todos os seus filhos o mesmoentão eles compartilham ume diferencie-os com a chave de classificação. DynamoDB não possui junções ou chaves estrangeiras, portanto o relacionamento reside no próprio esquema de chave. Carregar um pai mais cada filho torna-se um único Query em vez de uma junção.

  • Modele as leituras, não as entidades. O relacionamento um-para-muitos só existe para servir "listar os projetos de um espaço de trabalho" — molde as chaves em torno dessa consulta.
  • Codifique o pai no filho. Dê o espaço de trabalho e tudo ele projeta o mesmo valor de chave de partição para que caiam em um .
  • Então a lista lida é uma Query. Pai mais seus filhos voltam juntos — sem junção, sem segunda viagem de ida e volta (um Query retorna até 1 MB por página, paginando via LastEvaluatedKey além disso).
  • Assista ao. Um grande inquilino concentra todo o seu tráfego em um partição; um espaço de trabalho gigante pode precisar de uma chave fragmentada e de uma leitura em leque.

O padrão de acesso, primeiro

A modelagem DynamoDB prioriza o padrão de acesso, não a entidade – a mesma disciplina por trás do design de tabela única. Antes de escolher qualquer chave, anote as leituras que o aplicativo realmente emite:

  • Obtenha as configurações de um espaço de trabalho.
  • Liste todos os projetos em um espaço de trabalho, começando pelos mais recentes.
  • Obtenha um projeto específico por id.

O relacionamento “um espaço de trabalho, muitos projetos” só importa por causa da leitura nº 2. Se você nunca precisasse listar os projetos de um espaço de trabalho, você não modelaria o relacionamento - você armazenaria projetos de forma independente.

Portanto, a questão nunca é “como posso representar um para muitos?” no abstrato. É "quais consultas esse relacionamento deve atender?" Responda isso e depois molde as teclas em torno disso.

Por que uma chave estrangeira não ajudará aqui

Em DynamoDB cada GetItem e Query tem como alvo uma chave de partição, e o service faz hash dessa chave para localizar a partição que contém o item.

AWS diz isso diretamente nos Componentes principais docs: o valor da chave de partição é a entrada para uma função hash interna que decide onde os dados ficam.

Esse posicionamento baseado em hash é a herança do _Dynamo original de 2007: Artigo de armazenamento de valor-chave altamente disponível da Amazon, onde hashing consistente distribui chaves entre nós.

Um atributo workspace_id vazio em um item do projeto é invisível para aquele maquinaria — DynamoDB não pode "segui-la".

Para buscar itens relacionados em uma solicitação, a identidade do pai deve ser codificada em a chave de partição do projeto, para que todos os itens de um espaço de trabalho sejam hash para o mesmo partição e um Query pode varrê-las.

Exemplo prático: espaços de trabalho e projetos

Use um esquema de chave genérico e sobrecarregado. Chame a chave de partição EntityRef e o chave de classificação Detalhe. A identidade do espaço de trabalho vai para EntityRef para ambos os item do espaço de trabalho e todos os projetos sob ele:

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

O espaço de trabalho e todos os seus projetos compartilham EntityRef = "WS#acme", então eles formam um coleção de itens únicos vivendo juntos em uma partição.

A chave de classificação Detail os separa: META é o registro do espaço de trabalho, e cada projeto carrega um prefixo PROJ# com um ID ordenado por tempo e preenchido com zeros para que os projetos classifique naturalmente.

Visualmente, o pai e seus filhos são empilhados dentro de uma partição, ordenados pelo chave de classificação:

Partição: EntityRef = WS#acmeMETA configurações doworkspacePROJ#2026-0007PROJ#2026-0042PROJ#2026-0118

Um Query em EntityRef = "WS#acme" varre toda a pilha - pai mais cada criança - em uma única leitura.

Agora, cada um dos três padrões de acesso se reduz a uma chamada:

  • Configurações do espaço de trabalhoGetItem(EntityRef="WS#acme", Detail="META").
  • Listar os projetos mais recentesQuery(EntityRef="WS#acme") com Detalhe begins_with "PROJ#", executado em ordem decrescente (ScanIndexForward = falso).
  • Um projetoGetItem(EntityRef="WS#acme", Detail="PROJ#2026-0042").

O segundo é o ponto. O pai e seus filhos voltam de um Query, sem junção e sem segunda viagem de ida e volta — DynamoDB retorna até 1 MB por página e entrega a você um LastEvaluatedKey para buscar o resto. Esse é o movimento você não pode fazer isso com um atributo de chave estrangeira e um Scan.

Escrever essa condição begins_with manualmente é complicado - a condição-chave e mordidas de sintaxe de expressão de projeção.

O DynamoDB Expression Builder gera o KeyConditionExpression, os mapas de espaço reservado #name/:value e um snippet do SDK pronto para execução para que você não lute contra a gramática:

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

Inspecione a coleção de itens em DynoTable

Cada linha que compartilha um EntityRef é o espaço de trabalho mais seus filhos, sentados um ao lado do outro.

DynoTable os agrupa para que você veja o relacionamento um-para-muitos como um relacionamento contíguo bloquear em vez de adivinhar em tabelas separadas.

O item META da área de trabalho e seus filhos PROJ# agrupados como uma coleção de itens na visualização de tabela de DynoTable.
O item META da área de trabalho e seus filhos PROJ# agrupados como uma coleção de itens na visualização de tabela de DynoTable.

Armadilhas e a forma alternativa

Algumas coisas para observar:

  • Partições ativas. Cada item de um espaço de trabalho reside em uma partição, portanto, um único inquilino muito grande ou muito ocupado concentra o tráfego. O capacidade adaptativa comportamento AWS descreve absorve inclinação moderada, mas um espaço de trabalho com milhões de os projetos podem precisar de uma chave fragmentada (por exemplo, WS#acme#01… #10) e uma leitura de fan-out.
  • Tamanho da coleção de itens. Com um índice secundário local, uma única partição a coleta de itens é limitada a 10 GB; sem um LSI não existe tal limite. Se você está pesando tipos de índice aqui, veja GSI vs LSI.
  • Alcance Query, nunca Scan. Todo o design existe para que você possa Query uma partição. Voltando a um Scan filtrado para "encontrar um espaço de trabalho projetos" joga o modelo fora e lê a tabela inteira - a armadilha coberta em Query vs Scan.

Se você realmente precisa listar projetos em espaços de trabalho (digamos, todos status = ACTIVE projeta globalmente), a tabela base não pode responder a isso - é a chave de partição tem escopo no espaço de trabalho.

Esse é um trabalho para um índice secundário que reparticiona projetos em um local diferente. atributo, não para remodelar esse relacionamento.

Próximos passos

Modele os padrões de acesso, codifique o pai na chave de partição do filho e a leitura um-para-muitos é um único Query. Construa e valide a condição chave com o DynamoDB Expression Builder — e se você preferir começar pelos próprios padrões de acesso, o acesso gratuito Ferramenta de design de tabela única elabora o Plano PK/SK/GSI com itens de exemplo.

Então download DynoTable para carregar este esquema, navegue no espaço de trabalho→projetos coleção de itens ativa e confirme se cada consulta faz exatamente uma leia. Se você preferir ver espaços de trabalho e projetos como uma visão relacional e conjunta, DynoTable's SQL Workbench executa esse JOIN também.

Atualizado

Experimente este design de forma interativa

Esboce suas entidades e padrões de acesso na ferramenta gratuita de Single-Table Design do DynamoDB — ela sugere modelos de chave PK/SK, prevê as coleções de itens e mostra quais padrões precisam de um GSI.

Abrir a ferramenta de Single-Table Design