Single-table design no DynamoDB
Vindo do SQL, o instinto é uma tabela por entidade: customers, orders,
order_items. No DynamoDB, esse instinto costuma estar errado. Uma única tabela que
armazena cada entidade, distinguida por prefixos de chave sobrecarregados, permite que você busque
um pai e seus filhos em um único Query — sem joins, sem N+1.
O que é single-table design no DynamoDB?
O single-table design armazena cada entidade — clientes, pedidos, itens de pedido — em uma única
tabela do DynamoDB, distinguida por prefixos sobrecarregados de e
chave de ordenação. Como as chaves são projetadas em torno dos seus padrões de acesso
em vez das suas entidades, um pai e todos os seus filhos vivem em uma única
e voltam em um único Query — sem joins,
sem leituras N+1.
A ideia
Escolha nomes de chave genéricos (PK, SK) e codifique o tipo de 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 Query PK = "CUSTOMER#42" retorna o perfil e cada pedido em uma
única leitura cobrada. SK begins_with "ORDER#" a estreita apenas para os pedidos.
Visualmente, os itens sobrecarregados se empilham sob uma única como uma única :
Uma leitura da partição devolve o cliente e cada pedido juntos.
GSIs sobrecarregados
O mesmo truque funciona em índices. Coloque um GSI1PK/GSI1SK genérico nos itens, e um
único atende múltiplos padrões de acesso dependendo do que cada item grava
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 relações (um usuário em muitos times, um time com muitos usuários), grave 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 single-table
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 os dados são majoritariamente analíticos, tabelas separadas (ou um armazenamento diferente) podem ser a escolha mais sensata. O single-table vence quando os padrões são conhecidos e de alto volume.
O custo do formato errado
Modelar como tabelas separadas força um Scan ou um join no lado do cliente para remontar um
cliente, e esse é o footgun do Scan. Modele os padrões de acesso
primeiro, depois projete as chaves para tornar cada um deles um Query. (Para a
pergunta ad hoc entre entidades que você nunca modelou, o
SQL Workbench do DynoTable roda o JOIN no lado do
cliente — a exploração não precisa esperar uma remodelagem.)
Rascunhe o próprio design com a gratuita ferramenta de Single-Table Design — ela transforma sua lista de padrões de acesso em um plano PK/SK/GSI com itens de exemplo e dicas de custo. Estime o que esses itens custam por leitura com a calculadora de tamanho de item e capacidade, e experimente o DynoTable para navegar por um esquema single-table e ver as coleções sobrecarregadas lado a lado.