Tabela Única no DynamoDB
Vindo do SQL, o instinto é uma tabela por entidade: customers, orders,
order_items. No DynamoDB esse instinto geralmente está errado. Uma única tabela que
armazena todas as entidades, distinguidas por prefixos de chave sobrecarregados, permite buscar
um pai e seus filhos em um Query — sem joins, sem N+1.
Comece pelos padrões de acesso, não pelas entidades
A tabela única é orientada a padrões de acesso. Antes de escolher uma única chave,
anote cada leitura que seu app faz — "pegar o perfil de um cliente", "listar os
pedidos de um cliente do mais novo para o mais antigo", "encontrar todos os pedidos abertos" — porque as chaves existem
apenas para servir essa lista. A normalização relacional otimiza o armazenamento; a modelagem
do DynamoDB otimiza as consultas que você já sabe que vai rodar. Enumere-as e depois
projete chaves para que cada uma seja um único Query.
A ideia
Escolha nomes de chave genéricos (PK, SK) e codifique o tipo da entidade no valor:
| PK | SK | attributes |
|---|---|---|
| CUSTOMER#42 | PROFILE | name, email, plan |
| CUSTOMER#42 | ORDER#2026-001 | total, status |
| CUSTOMER#42 | ORDER#2026-002 | total, status |
Agora um único Query PK = "CUSTOMER#42" retorna o perfil e todos os pedidos em uma
única leitura cobrada. SK begins_with "ORDER#" o estreita só para os pedidos.
Visualmente, os itens sobrecarregados se empilham sob uma única chave de partição como uma única coleção de itens:
Uma leitura da partição devolve o cliente e todos os pedidos juntos.
GSIs sobrecarregados
O mesmo truque funciona em índices. Coloque um GSI1PK/GSI1SK genérico nos itens, e um
único GSI serve a múltiplos padrões de acesso dependendo do que cada item escreve
nesses atributos:
| PK | SK | GSI1PK | GSI1SK |
|---|---|---|---|
| ORDER#001 | METADATA | STATUS#OPEN | 2026-01-04 |
| ORDER#002 | METADATA | STATUS#OPEN | 2026-01-05 |
Agora Query GSI1 WHERE GSI1PK = "STATUS#OPEN" lista os pedidos abertos por data — um
padrão que a tabela base não consegue responder. Uma entidade diferente pode reutilizar o GSI1 com seu
próprio significado (por exemplo, CATEGORY#books). Um índice, muitas consultas.
Muitos-para-muitos: a lista de adjacência
Para relacionamentos (um usuário em muitos times, um time com muitos usuários), escreva a aresta
duas vezes com os ids trocados: PK=USER#1, SK=TEAM#9 e PK=TEAM#9, SK=USER#1.
Consultar qualquer um dos lados lista o outro — o substituto do DynamoDB para uma tabela de junção.
Quando não usar tabela única
Não é de graça. Uma tabela sobrecarregada é mais difícil de raciocinar, mais difícil de evoluir e hostil a análises. Se seus padrões de acesso são genuinamente desconhecidos ou mudam constantemente, ou se os dados são em sua maioria analíticos, tabelas separadas (ou um armazenamento diferente) podem ser a escolha mais sensata. A tabela única vence quando os padrões são conhecidos e de alto volume.
O custo da forma errada
Modelar como tabelas separadas força um Scan ou um join no lado do cliente para remontar um
cliente, e essa é a armadilha do Scan. Modele os padrões de acesso
primeiro e depois projete chaves para tornar cada um deles um Query.
Estime quanto esses itens custam por leitura com a calculadora de tamanho de item e capacidade e experimente o DynoTable para navegar por um schema de tabela única e ver as coleções sobrecarregadas lado a lado.