O que é modelagem de dados?

Atualizado em: agosto de 2026

A modelagem de dados é o processo de mapear entidades, atributos e relacionamentos antes de decidir como o banco de dados vai armazená-los. As entidades são a parte fácil — todo produto conhece seus usuários, pedidos e posts. O ofício está nos relacionamentos: quais registros apontam para quais, quantos, e onde essa aresta vive fisicamente. Acerte as arestas e as queries se escrevem sozinhas; erre e cada feature briga com o schema.

Principais pontos

PerguntaResposta
Os três níveisConceitual (o quê) → lógico (estrutura) → físico (motor)
As três arestasUm-para-um · um-para-muitos · muitos-para-muitos
Ferramentas relacionaisChaves estrangeiras; tabelas de junção para muitos-para-muitos
Ferramentas de documentosEmbutir, Pointers (referências), Relations/arrays de IDs
A regra modernaModele pelos padrões de acesso — dados lidos juntos vivem juntos

Os mesmos relacionamentos, nos dois mundos

Relacional primeiro — a chave estrangeira carrega o um-para-muitos, e o muitos-para-muitos precisa se decompor por uma junção:

-- 1:N — a chave estrangeira vive no lado "muitos"
CREATE TABLE books (
  id        bigint PRIMARY KEY,
  title     text   NOT NULL,
  author_id bigint NOT NULL REFERENCES authors(id) ON DELETE CASCADE
);

-- M:N — nenhuma FK sozinha expressa isso; a tabela de junção guarda as duas chaves
CREATE TABLE book_genres (
  book_id  bigint REFERENCES books(id),
  genre_id bigint REFERENCES genres(id),
  added_at timestamptz DEFAULT now(),     -- junções podem carregar atributos
  PRIMARY KEY (book_id, genre_id)         -- chave composta: uma aresta, uma vez
);

Mundo dos documentos, mesmo modelo: a aresta um-para-muitos é um Pointer tipado, a muitos-para-muitos é uma Relation — nenhuma tabela de junção para inventar, e a aresta é declarada no código da aplicação:

// JavaScript / Node.js — Back4app JS SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
const author = await new Parse.Query('Author').get(authorId);

const book = new Parse.Object('Book');
book.set('title', 'Dune');
book.set('author', author);              // Pointer — typed one-to-many edge
await book.save();

const genres = book.relation('genres');  // Relation — many-to-many, unbounded
genres.add([sciFi, classics]);
await book.save();

Conceitual vs. lógico vs. físico: os três níveis

Modelos de dados conceitual, lógico e físicoO modelo conceitual nomeia entidades e relacionamentos para a discussão de negócio; o modelo lógico adiciona atributos, tipos e chaves sem depender de tecnologia; o modelo físico se compromete com tabelas ou coleções, índices e constraints num motor de banco de dados específico.

Conceitual
Autor —escreve→ Livro
(o que existe, para humanos)

Lógico
+ atributos, tipos, chaves
(estrutura, sem motor definido)

Físico
tabelas/coleções, índices,
constraints num motor

O modelo conceitual nomeia entidades e relacionamentos para a discussão de negócio; o modelo lógico adiciona atributos, tipos e chaves sem depender de tecnologia; o modelo físico se compromete com tabelas ou coleções, índices e constraints num motor de banco de dados específico.
DimensãoConceitualLógicoFísico
Pergunta respondidaO que existe, como se relacionaQuais campos, quais chavesComo armazena, quão rápido
PúblicoTodo mundoDesigners do modeloEngenheiros + o motor
ContémEntidades, relacionamentos+ atributos, tipos, cardinalidade+ índices, constraints, partições
Muda quandoO negócio mudaOs requisitos se refinamO motor ou a escala mudam

A disciplina que os níveis impõem: não discuta índices enquanto o time ainda discorda sobre o que é um “pedido”.

Todo relacionamento, toda implementação

A tabela que a SERP nunca montou — cada tipo de aresta com sua implementação nos dois mundos:

RelacionamentoExemploImplementação relacionalImplementação em documentos
Um-para-umUsuário ↔ perfilFK com UNIQUE, ou a mesma linhaEmbutir — quase sempre
Um-para-poucosPessoa → endereçosTabela filha + FKArray embutido (limitado)
Um-para-muitosAutor → livrosFK no lado “muitos”Pointer no lado “muitos”
Um-para-enormesDispositivo → eventosFK + particionamentoPointer no filho; nunca um array
Muitos-para-muitosLivros ↔ gênerosTabela de junção, PK compostaRelation ou arrays de pointers
AutorreferênciaFuncionário → gerenteFK para a própria tabelaPointer para a própria classe

Notação de cardinalidade, para ler diagramas: o pé-de-galinha desenha uma barra para “um” e um garfo de três pontas para “muitos”; a tradição ER escreve 1 e N nas linhas; a UML escreve multiplicidades como 1 e *. Três dialetos, uma gramática.

Normalizar, desnormalizar ou embutir?

A modelagem relacional parte da normalização — separar os dados para que cada fato viva uma vez só, protegendo as escritas de anomalias. A modelagem analítica e a de documentos a dobram de propósito: a denormalização duplica campos quentes de leitura para matar joins, e embutir é a prima nativa dos documentos da denormalização. O checklist embutir-vs-referenciar se comprime em três perguntas: lidos juntos? de um dono só? tamanho limitado? Três sins embutem; qualquer não referencia. E, acima de tudo isso, a regra moderna que os guias generalistas pulam: liste as queries primeiro. Um modelo está correto quando os padrões de acesso que ele precisa servir saem baratos — as entidades sozinhas não contam isso.

Casos de uso comuns

  • Projetar um backend novo. O rito clássico: nomear entidades, desenhar arestas, escolher implementações pela tabela acima — antes da primeira linha de código.
  • O padrão junção-com-atributos. Matrículas, assinaturas, itens de pedido — quando a própria aresta tem dados (data, quantidade, papel), a junção (ou uma classe de aresta com dois pointers) é entidade de primeira classe.
  • Desembaraçar um schema que cresceu. Sintomas mapeiam para arestas: linhas duplicadas revelam um muitos-para-muitos mal modelado; documentos inchados revelam um embed sem limite.
  • Migrar entre os mundos. Relacional→documentos significa re-decidir cada FK como embed vs. pointer; a tabela acima é o dicionário de tradução.
  • Alimentar AI e analytics. Warehouses querem as arestas explícitas e estáveis — a dívida de modelagem aparece no dia em que você tenta exportar.

Como modelar cada aresta? Matriz de decisão

Escolha…Quando…Cuidado com…
EmbutirLidos juntos, um dono, tamanho limitadoCrescimento: o “poucos” de hoje vira os milhares de amanhã
Pointer / FKCiclo de vida independente, alta cardinalidadeIndexe — todo lookup e include paga
Relation / junçãoMuitos-para-muitos, ou a aresta carrega dadosDireção da query: saiba de que lado você vai perguntar
Duplicar (denormalizar)Um campo quente de leitura cruzando uma arestaFan-out de update — duplicação é dívida com juros

Limitações e trade-offs

  • Modelos congelam premissas. Decisões de cardinalidade (“um usuário tem um endereço”) viram schema; baratas no papel, caras depois do lançamento — modele para a cardinalidade de amanhã.
  • Os dois mundos punem a aresta sem índice. Colunas de FK e campos de pointer são caminhos de join; esquecer os índices deles é o bug silencioso de performance mais comum.
  • Embutir troca integridade por localidade. Nenhum motor garante que uma cópia embutida continue consistente com a fonte — isso agora é a sua lógica de update.
  • Junções multiplicam joins; Relations os escondem. Toda leitura muitos-para-muitos atravessa o armazém de arestas — orce o caminho da query, em qualquer um dos mundos.
  • Modelar por padrão de acesso também tem custo. Otimizar para as queries de hoje pode casar o schema com o produto de hoje; mantenha o modelo conceitual por perto como o terreno neutro da verdade.

Modelagem de dados no Back4app

O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. Seu vocabulário de modelagem é a coluna de documentos das tabelas acima, elevada a primeira classe: Pointers são arestas um-para-muitos tipadas, Relations carregam o muitos-para-muitos sem junção feita à mão, e arrays cobrem o “poucos e limitado”. Toda aresta que você declara é atravessável na hora — include() percorre pointers em uma requisição, o GraphQL aninha relações em uma query — e o schema segue visível e editável no dashboard, para que o modelo físico nunca saia do campo de visão do time que desenhou o conceitual.

Perguntas frequentes

O que é modelagem de dados?

O processo de mapear a informação de uma aplicação — suas entidades, os atributos delas e os relacionamentos entre elas — num design que um banco de dados consegue armazenar. Ele costuma atravessar três níveis de detalhe: um modelo conceitual nomeando as entidades, um modelo lógico adicionando atributos e chaves, e um modelo físico se comprometendo com tabelas, colunas e índices num motor específico.

Quais são os três tipos de modelos de dados?

Conceitual, lógico e físico — o mesmo design em zoom crescente. O conceitual responde "o que existe e como se relaciona" para o lado de negócio. O lógico adiciona atributos, tipos e chaves sem se prender a tecnologia. O físico se compromete com um motor real: tabelas ou coleções, índices, constraints. Cada nível é o anterior mais decisões.

O que é um relacionamento um-para-muitos?

Um registro pai relacionado a muitos filhos, cada filho pertencendo a exatamente um pai — um cliente e seus pedidos, um autor e seus livros. É o relacionamento mais comum de qualquer schema. Bancos relacionais o implementam com uma chave estrangeira no lado "muitos"; bancos de documentos usam um array embutido para conjuntos pequenos e limitados, ou um pointer para o pai em todo o resto.

O que é um relacionamento muitos-para-muitos e por que ele precisa de tabela de junção?

Os dois lados se relacionam com muitos do outro — alunos e cursos, livros e gêneros. Uma coluna de chave estrangeira só consegue apontar para uma linha, então bancos relacionais decompõem o muitos-para-muitos em dois um-para-muitos através de uma tabela de junção com as duas chaves (e, muitas vezes, atributos da relação, como a data de matrícula). Bancos de documentos dispensam a junção: arrays de referências, ou um tipo dedicado de relação, carregam a aresta diretamente.

Como diferenciar um-para-muitos de muitos-para-muitos?

Faça a pergunta de posse nos dois sentidos. "Um autor pode ter muitos livros?" Sim. "Um livro pode ter muitos autores?" Se não — um-para-muitos, chave estrangeira no livro. Se sim — muitos-para-muitos, tabela de junção ou Relation. Errar aqui é o erro clássico de modelagem: um muitos-para-muitos modelado como um-para-muitos ou duplica linhas ou perde arestas em silêncio.

O que é cardinalidade em um diagrama ER?

Quantas instâncias de uma entidade podem se relacionar com instâncias de outra — um-para-um, um-para-muitos, muitos-para-muitos. Os diagramas expressam isso em uma de três notações: números e letras nas linhas de conexão, os símbolos pé-de-galinha (uma barra para "um", um garfo de três pontas para "muitos"), ou faixas de multiplicidade como 1 e asterisco. Mesma semântica, convenções de desenho diferentes.

Como bancos de documentos modelam relacionamentos sem chaves estrangeiras?

Com três ferramentas: embutir (aninhar os dados relacionados dentro do documento pai — certo quando são lidos juntos, têm um dono só e tamanho limitado), pointers ou referências (guardar o ID do documento relacionado como campo tipado — certo para ciclos de vida independentes e alta cardinalidade), e objetos Relation ou arrays de IDs para muitos-para-muitos. A regra-guia troca a normalização pelos padrões de acesso: dados lidos juntos devem viver juntos.

Quais são os erros mais comuns de modelagem de dados?

Um top cinco estável: modelar muitos-para-muitos como um-para-muitos; esquecer índices nos campos de chave estrangeira e de pointer (todo join e lookup paga por isso); arrays embutidos sem limite de crescimento em schemas de documento; denormalização prematura antes de qualquer query se provar lenta; e modelar só a partir das entidades, sem listar as queries — os padrões de acesso — que o modelo precisa servir.

Termos relacionados

Compare com

Leitura adicional

Pronto para construir seu backend?

Comece seu projeto no Back4app em minutos — banco de dados, autenticação, APIs e Cloud Code incluídos. Sem cartão de crédito.

Escrito e revisado por Back4app Engineering, Back4app Engineering · Publicado em 2026-08-21