Armazéns de dados e NoSQL
Grão, esquemas multidimensionais, ETL, OLAP, famílias NoSQL e consultas MongoDB.
Do operacional ao analítico
OLTP serve operações correntes (reservar, criar, atualizar) com transações curtas e dados atuais. Um armazém de dados integra fontes por assunto, com histórico, para análise; carrega em lotes e pode estar atrasado. “Não volátil” quer dizer relativamente estável, não incorrigível nem isento de transações.
O grão fixa o que é uma linha do facto; na loja, um produto numa encomenda. A tabela de factos guarda medidas e referências a dimensões (produto, tempo, cliente).
Não mistures totais de encomenda com linhas de produto na mesma medida. Para analisar a cidade à data da compra, conserva versões históricas em vez de reescrever o passado.
Medir sem pesar mal
| Medida | Como agregar sem errar |
|---|---|
| Aditiva | Soma por produto, cliente ou tempo, com unidades compatíveis. |
| Semiaditiva | Saldos somam entre contas na mesma data; nunca somes saldos ao longo do tempo. |
| Não aditiva | Percentagens e razões calculam-se dos totais, não de médias de médias. |
Na loja: 7 unidades e 37000 cêntimos. O preço médio é (cerca de 52,86 euros); a média simples dos quatro preços (68,75) pesa mal as quantidades. O grão decide o que cada soma significa.
- Estrela: facto ligado direto a dimensões, em geral desnormalizadas.
- Floco de neve: normaliza dimensões, com mais junções.
- Constelação: factos partilham dimensões; agrega cada um ao nível comum antes de juntar, para não multiplicar medidas.
ETL extrai, transforma (ids, unidades, histórico) e carrega por ordem das referências. Um data mart foca um assunto; dependente deriva do armazém, independente integra fontes próprias.
Operar o cubo
| Operação | Efeito sobre o detalhe |
|---|---|
| Roll-up | Agrega, como dias em meses. |
| Drill-down | Desce ao detalhe existente. |
| Slice | Fixa uma dimensão. |
| Dice | Recorta subconjuntos em várias dimensões. |
| Pivot | Rearranja eixos, sem mudar factos. |
| Drill-across | Compara factos por dimensões compatíveis. |
ROLLUP(ano, categoria) dá (ano,categoria), ano e total; CUBE junta só categoria. SQLite não os tem: constrói níveis com UNION ALL. Com GROUPING, distingue nulos de subtotal de desconhecidos.
Escolher armazenamento e distribuir
| Família | Serve para |
|---|---|
| Chave-valor | Valor pela chave: sessões, caches. |
| Documentos | Objetos com campos e arrays, consultados por conteúdo. |
| Famílias de colunas | Linhas por chave, colunas flexíveis, acesso distribuído. |
| Grafos | Nós e arestas para percursos e relações. |
Famílias de colunas não são armazenamento colunar analítico. NoSQL não significa sem validação nem sem ACID: as garantias são por produto e operação.
Replicação copia; sharding parte por chave. Chave desigual concentra carga. Sob partição de rede, CAP impede consistência linearizável e disponibilidade total em simultâneo; não é a consistência de invariantes do ACID. Consistência eventual converge quando a comunicação permite, com regras de conflito; BASE é orientação, não garantia.
Consultar documentos
Comandos de mongosh, não SQLite:
db.produtos
.find({ preco: { $gt: 30 } }, { _id: 0, nome: 1, preco: 1 })
.sort({ preco: -1, nome: 1 });
Preço acima de 30, nome e preço por ordem decrescente. Inclusão não se mistura com exclusão, exceto _id. "detalhes.layout" lê aninhado; { categorias: "entrada" } testa elemento do array.
$setaltera campos,$incincrementa;updateOnetoca um documento,updateManytodos os correspondentes. Substituir o documento apaga omitidos. Filtro pornullpode apanhar documentos sem o campo.distinctlista valores;countDocumentsconta documentos do filtro.
No pipeline, $match filtra, $project escolhe/calcula, $unwind desdobra arrays, $group agrega, $sort ordena. Teclado (duas categorias) mais Rato (uma) dão três ocorrências, não três produtos. $lookup junta correspondências num array (vazio sem correspondência, sem eliminar a linha). $facet corre subpipelines independentes e devolve um array por saída.