Específicos · Bancos de Dados
Modelagem NoSQL: orientada a consultas, desnormalização, agregados
O relacional parte do dado e normaliza; aqui se parte da consulta e se duplica de propósito. O custo não some: sai da leitura e reaparece na escrita.
Média
Nenhum item de prova anterior, no acervo deste projeto, caiu neste tópico. A nota foi escrita a partir do edital e da bibliografia — não do corpus — e por isso não traz frequências medidas.
A ideia que organiza o assunto
A modelagem relacional começa pelos dados: descobre-se que entidades existem, normaliza-se para eliminar redundância, e só depois se escrevem as consultas — que o otimizador atende com junções, sejam elas quais forem. O modelo é independente da pergunta: um esquema normalizado responde bem a consultas que ninguém imaginou quando ele foi desenhado.
A modelagem NoSQL inverte a ordem. Começa-se pelas consultas: enumeram-se os padrões de acesso da aplicação — quem lê o quê, com que filtro, com que frequência, em que ordem — e projeta-se, para cada um deles, uma estrutura que o atenda em uma única leitura. Como o mesmo dado costuma ser necessário em padrões de acesso diferentes, ele é gravado em mais de um lugar, de propósito.
Isso não é normalização mal feita. É uma troca deliberada, e ela tem nome dos dois lados:
- no relacional, a redundância é defeito e a junção é o preço de eliminá-la;
- aqui, a junção é impossível ou cara (não existe em Cassandra, é limitada e custosa em bancos de documentos), então a redundância vira ferramenta e a consistência entre as cópias passa a ser responsabilidade da aplicação.
Daí decorrem as três consequências que organizam o resto da nota. Primeira: não se modela NoSQL sem conhecer as consultas — o modelo relacional errado custa desempenho; o modelo NoSQL errado custa a consulta, que simplesmente não pode ser feita. Segunda: o custo não desaparece, muda de lado — a leitura fica barata e a escrita fica cara, porque uma alteração lógica vira várias escritas. Terceira: quem decide onde a redundância começa e termina é o agregado, a unidade que é lida, gravada, replicada e distribuída como um bloco só.
Por que se usa (e o que custa)
O ganho é medido na leitura e na distribuição. Uma tela que no relacional
exigiria sete junções vira um get por chave, e como o agregado é
autocontido ele pode viver inteiro em um nó do cluster: a consulta não precisa
falar com três máquinas, o que é exatamente o que permite escalar
horizontalmente. O agregado é também a fronteira de atomicidade — bancos de
chave-valor, de documentos e de famílias de colunas garantem escrita atômica
dentro de um agregado, e nada além disso.
O custo tem três parcelas, e ignorá-las é o que produz item errado.
A escrita multiplica. Um nome de produto duplicado em cinquenta mil pedidos é uma atualização em cinquenta mil documentos. Enquanto ela corre, há uma janela em que as cópias divergem — consistência eventual não é só um slogan de CAP, é o estado real dos dados desnormalizados durante a propagação.
A aplicação herda a integridade. Não há chave estrangeira, não há CASCADE,
não há restrição declarada que impeça a cópia de envelhecer. O que no relacional
o SGBD garantia passa a depender de código — e de código que alguém precisa
lembrar de escrever em todos os pontos de escrita.
O modelo endurece contra o futuro. Um padrão de acesso que ninguém previu
não se resolve com um JOIN improvisado: resolve-se remodelando e reescrevendo
os dados. É a rigidez que a flexibilidade de esquema esconde — e a razão de dado
muito relacionado, consulta imprevisível e integridade forte continuarem sendo
terreno do relacional.
Como funciona
1. Levantar os padrões de acesso. Antes de qualquer estrutura: quais são as consultas, quais filtram por quê, qual a proporção entre leitura e escrita, qual o volume e como ele cresce. Esse levantamento faz, aqui, o papel que o modelo conceitual faz lá — e o modelo conceitual não desaparece: entidades e relacionamentos continuam sendo levantados; o que muda é a tradução deles para o modelo lógico.
2. Desenhar a fronteira do agregado. A pergunta é: o que é lido junto e alterado junto? O que se lê junto entra no mesmo agregado; o que é acessado de forma independente, ou é compartilhado por muitos agregados, fica fora e é referenciado. Endereço de entrega pertence ao pedido; catálogo de produtos, não.
3. Embutir ou referenciar, pela cardinalidade. É a decisão concreta em banco de documentos:
- 1:1 e 1:poucos — embutir. O subdocumento vem de graça na mesma leitura.
- 1:muitos — embutir um subconjunto (os dez itens mais recentes, por exemplo) e manter o resto em coleção própria.
- 1:incontáveis — referenciar do lado muitos para o um: o filho guarda a chave do pai, porque um documento que cresce sem limite estoura o tamanho máximo e fica caro de reescrever a cada inserção.
Embuta também quando os dados mudam juntos; referencie quando a parte embutida mudaria com frequência muito maior que o todo.
4. Desnormalizar com intenção. A forma mais comum é a referência estendida: além da chave do outro documento, copiam-se os poucos campos que a tela precisa mostrar — o nome do cliente dentro do pedido, para não ter de buscar o cliente. Copia-se o que muda pouco; o que muda muito permanece referenciado. Outros padrões da mesma família guardam valores já calculados (totais, contadores) em vez de recalculá-los a cada leitura, e agrupam séries temporais em blocos — um documento por hora, com as leituras dentro, em vez de um documento por leitura.
5. Uma tabela por consulta, no colunar. Em Cassandra a regra é literal:
modela-se uma tabela para cada consulta que a aplicação faz, duplicando os dados
entre elas. A chave primária combina chave de partição (que determina em que
nó o dado mora, e sem a qual a consulta não se faz) e colunas de agrupamento
(que determinam a ordenação dentro da partição). A cláusula WHERE só aceita o
que a chave permite, não há junção, e recorrer a ALLOW FILTERING é sinal de
que o modelo não previu aquela consulta.
6. Manter as cópias em dia. Ou a aplicação escreve em todos os lugares na mesma operação, ou um processo assíncrono propaga a mudança depois, mais barato e com janela de divergência assumida. Nos dois casos a decisão é de quem modela — o banco não faz isso sozinho.
“NoSQL não tem esquema” é falso, e em três níveis. No mais literal, vários produtos exigem esquema declarado: Cassandra exige tabela criada com colunas tipadas, e Elasticsearch tem mapping, explícito ou inferido, que uma vez fixado não muda para um campo existente. No intermediário, os que não exigem oferecem validação opcional — bancos de documentos permitem declarar regras de validação por coleção. E no nível que interessa: mesmo sem nenhuma declaração, o esquema existe no código da aplicação, que espera certos campos com certos tipos. É o schema-on-read: a validação foi deslocada da escrita para a leitura, não suprimida. Documentos de formatos diferentes convivendo na mesma coleção obrigam o código a tratar todas as versões — por isso a prática de gravar um campo de versão do esquema.
O que decide os itens
| par que a banca troca | o que decide |
|---|---|
| Modelagem relacional × orientada a consultas | O relacional parte dos dados e normaliza; o NoSQL parte das consultas e duplica. Ordem inversa, e é isso que o item inverte. |
| Normalizar × desnormalizar | Normalizar elimina redundância e paga em junções; desnormalizar elimina junções e paga em escrita e em risco de divergência. |
| Custo eliminado × custo deslocado | A desnormalização não torna tudo mais barato: barateia a leitura e encarece a escrita e a manutenção. |
| Agregado × entidade | O agregado é a unidade de leitura, escrita, replicação e distribuição — e a fronteira da atomicidade. Pode reunir várias entidades. |
| Embutir × referenciar | Lido junto e alterado junto, embute; acessado à parte, compartilhado ou de crescimento ilimitado, referencia. |
| 1:poucos × 1:incontáveis | Poucos, embutidos; incontáveis, referenciados do lado muitos — documento que cresce sem limite é defeito de modelagem. |
| Integridade no SGBD × na aplicação | Sem chave estrangeira e sem CASCADE, a coerência entre cópias é código da aplicação. |
| Schema-on-write × schema-on-read | A validação mudou de momento, não deixou de existir. Cassandra e Elasticsearch exigem estrutura declarada. |
| “Sem esquema” × “esquema flexível” | Flexível: campos podem variar entre documentos. Isso não é ausência de contrato — é contrato mantido fora do banco. |
| Modelo conceitual × modelo lógico | O conceitual permanece; muda a tradução para o lógico. NoSQL não dispensa modelagem: exige outra. |
| Agregado × grafo | Bancos de grafos são indiferentes a agregado: não se desnormaliza um grafo, percorrem-se arestas. A regra query-first não se aplica a eles do mesmo jeito. |
| Desnormalização dimensional × desnormalização NoSQL | No data warehouse, desnormaliza-se a dimensão por desempenho analítico; aqui, desnormaliza-se por padrão de acesso e ausência de junção. Mesmo movimento, motivos diferentes. |
| Uma tabela por consulta × uma tabela por entidade | No colunar, a mesma informação vive em várias tabelas, uma por consulta. Não é erro de projeto: é o projeto. |
Como a CEBRASPE derruba você aqui
Esta seção é julgamento sobre como a banca costuma cobrar o assunto — não medição. Não há itens deste tópico no acervo para medir.
A inversão da ordem do processo. É o item mais natural do tópico e o mais fácil de não ver: “na modelagem NoSQL, projeta-se primeiro a estrutura dos dados e, a partir dela, derivam-se as consultas”. A frase descreve corretamente o método — só que o método é o do relacional. Defesa: leia a descrição até o fim, decida sozinho a que abordagem ela pertence e só então confira o nome que o item deu.
A vantagem sem o custo. “A desnormalização melhora o desempenho de leitura e de escrita”, “elimina a necessidade de controle de consistência”, “reduz o espaço ocupado”. Todas soam plausíveis porque a primeira metade é verdadeira. O teste é sempre o mesmo: o que a desnormalização barateia é a leitura, e escrita, espaço e consistência vão na direção contrária.
“NoSQL dispensa modelagem” e suas variantes. “Dispensa a definição de modelo lógico”, “não admite esquema”, “a ausência de esquema impede a indexação”. O que existe é esquema validado na leitura ou declarado fora do banco; e há produtos que exigem declaração prévia. Quando o item negar a existência de esquema em bloco, ele está errado.
A fronteira do agregado trocada pela da entidade. Um item que trate agregado como sinônimo de tabela, ou que afirme que a atomicidade se estende a vários agregados, está apagando exatamente aquilo que o agregado define. Garantia atômica existe dentro de um agregado.
O documento sem limite. “Em um banco de documentos, recomenda-se embutir todas as ocorrências do lado muitos de um relacionamento.” Não se recomenda: há limite de tamanho de documento, e um arranjo que cresce indefinidamente torna cada leitura e cada escrita mais caras. Embute-se o que é pequeno e limitado.
Quando o absoluto é da definição. “O agregado é a unidade de distribuição”, “em Cassandra, toda consulta eficiente informa a chave de partição”, “os mesmos dados são intencionalmente repetidos em várias tabelas” — parecem exageros e são o desenho do modelo. A pergunta continua sendo de quem é o absoluto: do produto e da definição, ou do redator do item.
Erros clássicos
Achar que modelagem orientada a consultas é modelagem relacional sem normalizar. É outra ordem de trabalho: as consultas vêm antes das estruturas.
Tratar desnormalização como ganho sem contrapartida. Ela transfere o custo para a escrita e para a consistência entre as cópias.
Esperar que o banco mantenha as cópias coerentes. Não há chave estrangeira nem propagação automática: é código da aplicação ou processo assíncrono.
Embutir coleções ilimitadas. Documento que cresce sem teto estoura o limite de tamanho e encarece toda leitura.
Referenciar o que é sempre lido junto. O erro simétrico: obriga a segunda ida ao banco justamente onde o modelo existia para evitá-la.
Ler schemaless como ausência de contrato. O contrato mudou de lugar — está na aplicação, no mapping ou na validação da coleção.
Duplicar dados voláteis. Copia-se o que muda pouco; o campo que muda toda hora deve ficar referenciado, ou a divergência vira rotina.
Modelar um grafo como se fosse agregado. Em banco de grafos não se desnormaliza: o que dá desempenho é percorrer arestas, e o modelo é próximo do conceitual, não derivado das consultas.
Tratar a modelagem como definitiva. Padrão de acesso novo pode exigir estrutura nova e reescrita dos dados: é o preço de ter otimizado para os padrões conhecidos.
LidoPraticado