# Armazéns de dados e NoSQL

Modelo multidimensional, OLAP e quando trocar o relacional.

Página: https://resumos.rgo.pt/cadeiras/bd/armazens-dados-nosql/

O modelo relacional foi desenhado para o dia a dia da loja: registar cada venda depressa e sem contradições (o mundo **OLTP**). Mas responder a “como evoluíram as vendas por categoria e mês no último ano” sobre esse esquema é juntar quatro tabelas e agregar milhões de linhas. Para análise há um modelo próprio, e para dados sem esquema fixo há outro. Saber escolher entre os três é o último resultado de aprendizagem da cadeira.

## Armazém de dados e OLAP

Um **armazém de dados** (_data warehouse_) copia periodicamente os factos operacionais para um esquema otimizado para leitura e análise (**OLAP**). A organização típica é em **estrela**: uma tabela de factos central com medidas (quantidade, valor) rodeada de tabelas de dimensões (tempo, produto, cliente, loja). A pergunta anual acima vira uma agregação direta sobre a estrela, sem junções de normalização pelo caminho.

![Esquema em estrela: a tabela de factos Vendas ao centro, com quantidade e valor, rodeada pelas dimensões Tempo, Produto e Cliente.](https://resumos.rgo.pt/cadeiras/bd/armazens-dados-nosql/figura-1.svg)

Navegar no cubo tem quatro operações com nome próprio. Imagina sempre a estrela de vendas da loja:

*   **Roll-up**: subir na hierarquia e agregar. De vendas por dia para vendas por mês: somas os dias e perdes detalhe.
*   **Drill-down**: o inverso, descer na hierarquia. De vendas por mês para vendas por dia: abres o mês e vês os dias.
*   **Slice**: fixar uma dimensão. Só as vendas do Monitor: prendes a dimensão produto num valor e analisas o resto.
*   **Dice**: recortar um subcubo em várias dimensões. Vendas do Monitor à Ana no primeiro trimestre: prendes produto, cliente e tempo de uma vez.

Um relatório mensal é um roll-up temporal direto. Executa sobre os dados da loja:

```sql
CREATE TABLE Encomenda(id INTEGER PRIMARY KEY, data TEXT NOT NULL);
CREATE TABLE Item(idEncomenda INTEGER REFERENCES Encomenda(id), idProduto INTEGER REFERENCES Produto(id), qtd INTEGER NOT NULL, PRIMARY KEY (idEncomenda, idProduto));
CREATE TABLE Produto(id INTEGER PRIMARY KEY, nome TEXT NOT NULL, preco REAL NOT NULL);
INSERT INTO Encomenda VALUES (100, '2026-01-05'), (101, '2026-01-12'), (102, '2026-01-08');
INSERT INTO Produto VALUES (10, 'Teclado', 45.0), (11, 'Rato', 25.0), (12, 'Monitor', 180.0);
INSERT INTO Item VALUES (100, 10, 2), (100, 11, 1), (101, 12, 1), (102, 11, 3);
SELECT strftime('%Y-%m', Encomenda.data) AS mes, SUM(Item.qtd * Produto.preco) AS total FROM Encomenda JOIN Item ON Item.idEncomenda = Encomenda.id JOIN Produto ON Produto.id = Item.idProduto GROUP BY mes;
```

O resultado é `2026-01|370.0`: 115 da encomenda 100, 180 da 101 e 75 da 102, somadas pelo mês. Numa estrela a sério, o `mes` viria da dimensão tempo em vez do `strftime`, mas a agregação é a mesma.

O preço é claro: os dados do armazém têm a idade da última carga, nunca o segundo atual, e manter dois sistemas custa. Usa armazém quando as perguntas são analíticas, agregadas e históricas; mantém o relacional para o registo operacional do momento.

## NoSQL em quatro sabores

**NoSQL** não é “sem SQL” por capricho: é abdicar do esquema rígido e, muitas vezes, de parte do ACID em troca de escala ou flexibilidade. As quatro famílias, com o Teclado da loja em cada uma:

Um dicionário gigante distribuído: cada acesso é por chave exata. Serve para sessões, carrinhos e caches.

```
produto:10 -> { nome: Teclado, preco: 45.0, stock: 20 }
```

Objetos semiestruturados, como JSON, com esquema flexível por documento. Serve para catálogos, onde cada produto tem os seus atributos.

```
{ "id": 10, "nome": "Teclado", "extras": { "layout": "PT", "rgb": true } }
```

Tabelas guardadas por colunas em vez de linhas, ótimas para agregar uma coluna sobre milhões de linhas. Serve para telemetria e analítica.

```
coluna preco: [45.0, 25.0, 180.0]   -- lê só a coluna pedida
```

Nós e arestas como cidadãos de primeira classe. Serve para redes sociais e recomendações, onde as perguntas são sobre ligações.

```
(Ana)-[:COMPROU]->(Teclado)   -- a compra é uma aresta, não uma tabela
```

## A tabela de decisão

| Situação | Escolha | Porquê |
| --- | --- | --- |
| Registar vendas da loja sem contradições | Relacional | Integridade e transações por cada escrita |
| Relatório anual de vendas por mês e categoria | Armazém de dados | Agregações históricas sobre a estrela, sem pesar no operacional |
| Catálogo onde cada produto tem atributos próprios | Documento (NoSQL) | Esquema flexível, sem colunas nulas para todos |
| Carrinho de compras com milhões de acessos por chave | Chave-valor (NoSQL) | Leitura e escrita por chave a grande escala |

A pergunta de teste típica dá-te um cenário e pede a escolha justificada: identifica primeiro o padrão de acesso (escritas com integridade, análise agregada ou escala sem esquema) e só depois casa com a coluna da esquerda. E quando o cenário mistura os dois mundos, como a loja real, a resposta honesta é híbrida: relacional para operar, armazém para analisar.

## Para ver em vídeo

[Vídeo: Introduction to NoSQL • Martin Fowler • GOTO 2012](https://www.youtube.com/watch?v=qI_g07C_Q5I)

A miniatura vem do YouTube. O vídeo só carrega quando clicas. [Abrir no YouTube](https://www.youtube.com/watch?v=qI_g07C_Q5I)

[Vídeo: An Introduction To NoSQL Databases](https://www.youtube.com/watch?v=uD3p_rZPBUQ)

A miniatura vem do YouTube. O vídeo só carrega quando clicas. [Abrir no YouTube](https://www.youtube.com/watch?v=uD3p_rZPBUQ)
