Tota aplicació necessita, tard o d'hora, desar dades que sobrevisquin al reinici del procés. La decisió sobre com i on persistir aquestes dades és una de les més influents i duradores de qualsevol arquitectura: condiciona el rendiment, l'escalabilitat, la consistència i fins i tot el cost d'operació. Durant dècades la resposta per defecte va ser "una base de dades relacional", però l'explosió d'aplicacions web a gran escala va popularitzar un ventall d'alternatives agrupades sota el terme NoSQL. En aquesta lliçó aprendràs les diferències reals entre tots dos mons, quines garanties ofereixen (ACID enfront de BASE), quines famílies de bases NoSQL existeixen i, sobretot, quins criteris objectius fer servir per triar. L'objectiu no és declarar un guanyador, sinó que sàpigues raonar la decisió.
Contingut
- El model relacional (SQL) en essència
- Què significa realment "NoSQL"
- Les quatre famílies NoSQL: documental, clau-valor, columnar i graf
- Garanties transaccionals: ACID enfront de BASE
- Taula comparativa SQL vs NoSQL
- Criteris d'elecció i antipatrons
- Persistència poliglota
- El model relacional (SQL) en essència
Una base de dades relacional organitza les dades en taules (relacions) formades per files i columnes, amb un esquema rígid definit per endavant. Les relacions entre taules s'expressen mitjançant claus foranes, i consultem les dades amb SQL (Structured Query Language). Exemples: PostgreSQL, MySQL, Oracle, SQL Server.
Vegem un esquema relacional senzill per a clients i les seves comandes:
-- Taula de clients: cada client té un identificador únic
CREATE TABLE clientes (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
nombre VARCHAR(120) NOT NULL,
email VARCHAR(180) NOT NULL UNIQUE,
creado_en TIMESTAMP NOT NULL DEFAULT now()
);
-- Taula de comandes: la columna cliente_id "apunta" a clientes.id
CREATE TABLE pedidos (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
cliente_id BIGINT NOT NULL REFERENCES clientes(id),
total NUMERIC(10,2) NOT NULL CHECK (total >= 0),
estado VARCHAR(20) NOT NULL DEFAULT 'PENDIENTE'
);Analitzem el codi fragment a fragment:
PRIMARY KEY GENERATED ALWAYS AS IDENTITY: defineix la clau primària, l'identificador únic de cada fila. La base la genera automàticament, així que mai no hi haurà dos clients amb el mateixid.UNIQUEaemail: la base garanteix que no es repeteixi cap correu. És una regla d'integritat que viu a les dades, no al codi de l'aplicació.REFERENCES clientes(id): declara una clau forana. La base impedeix inserir una comanda elcliente_idde la qual no existeixi, evitant "comandes òrfenes". Això s'anomena integritat referencial.CHECK (total >= 0): una restricció que rebutja totals negatius. De nou, la regla l'aplica el motor.
Per recuperar les comandes d'un client combinem totes dues taules amb un JOIN:
SELECT c.nombre, p.id AS pedido_id, p.total FROM clientes c JOIN pedidos p ON p.cliente_id = c.id -- uneix files que comparteixen l'id WHERE c.email = '[email protected]' ORDER BY p.total DESC;
El JOIN és l'operació estrella del model relacional: permet compondre dades normalitzades (sense duplicació) en el moment de la consulta. La fortalesa és la flexibilitat per fer preguntes no previstes; el cost és que els JOIN molt grans poden ser lents i difícils d'escalar horitzontalment.
- Què significa realment "NoSQL"
"NoSQL" és un nom desafortunat: no significa "sense SQL" (moltes d'aquestes bases ofereixen llenguatges de consulta semblants) sinó "Not Only SQL". Agrupa motors que renuncien totalment o parcialment al model relacional per guanyar en escalabilitat horitzontal, flexibilitat d'esquema o rendiment en accessos concrets. Els seus trets habituals:
- Esquema flexible: cada registre pot tenir camps diferents sense migracions prèvies.
- Escalat horitzontal natiu: estan dissenyades per repartir dades entre molts nodes (sharding) des del primer dia.
- Desnormalització: en lloc de
JOIN, es dupliquen dades perquè cada lectura toqui un sol registre. - Garanties relaxades: sovint sacrifiquen la consistència immediata a canvi de disponibilitat i velocitat.
- Les quatre famílies NoSQL
No totes les bases NoSQL són iguals. Es classifiquen en quatre grans famílies segons el seu model de dades:
3.1 Documental
Emmagatzemen documents autocontinguts, normalment en JSON/BSON. Cada document agrupa tota la informació relacionada. Exemples: MongoDB, Couchbase. El mateix client amb les seves comandes de l'exemple SQL es veuria així en un únic document:
{
"_id": "cli_1042",
"nombre": "Ana López",
"email": "[email protected]",
"pedidos": [
{ "pedido_id": "ped_5001", "total": 49.90, "estado": "ENVIADO" },
{ "pedido_id": "ped_5002", "total": 12.50, "estado": "PENDIENTE" }
]
}Observa la diferència clau respecte a SQL:
- Les comandes estan incrustades dins del client, en un array
pedidos. Per mostrar la fitxa del client amb les seves comandes n'hi ha prou amb una sola lectura, senseJOIN. - No hi ha esquema fix: un altre client podria no tenir el camp
pedidos, o tenir un camptelefonoaddicional, sense que ningú hagi d'alterar la "taula". - El preu d'aquesta comoditat és la duplicació: si el nom d'un producte canvia i està copiat en milers de documents, cal actualitzar-los tots.
3.2 Clau-valor
El model més simple: un diccionari gegant que associa una clau a un valor opac. Exemples: Redis, DynamoDB (en el seu ús bàsic). Ideal per a sessions, cachés i comptadors. Pseudocodi d'accés:
És extremadament ràpid perquè l'operació és un accés directe per clau, però no es pot consultar pel contingut del valor: només es cerca per la clau exacta.
3.3 Columnar (wide-column)
Emmagatzemen les dades per columnes/famílies de columnes en lloc de per files, optimitzades per a escriptures massives i lectures de rangs enormes. Exemples: Apache Cassandra, HBase. Brillen en sèries temporals i registres d'esdeveniments a escala de petabytes.
3.4 Graf
Modelen entitats (nodes) i les seves relacions (arestes) com a ciutadans de primera classe. Exemples: Neo4j, Amazon Neptune. Quan l'important són les relacions profundes (xarxes socials, detecció de frau, recomanacions, "amics d'amics"), recorren connexions de manera moltíssim més eficient que un JOIN recursiu en SQL.
- Garanties transaccionals: ACID enfront de BASE
Aquí hi ha la diferència conceptual més important. Una transacció és un conjunt d'operacions que han de tractar-se com una unitat.
ACID (propi del món relacional) garanteix:
| Lletra | Propietat | Significat |
|---|---|---|
| A | Atomicitat | Tot o res: o s'apliquen totes les operacions o cap. |
| C | Consistència | La base passa d'un estat vàlid a un altre de vàlid (es respecten les restriccions). |
| I | Aïllament | Les transaccions concurrents no s'interfereixen entre si. |
| D | Durabilitat | Un cop confirmada, sobreviu a les caigudes del sistema. |
Exemple clàssic: transferir diners entre dos comptes ha de ser atòmic.
BEGIN; -- inicia la transacció UPDATE cuentas SET saldo = saldo - 100 WHERE id = 1; -- resta del compte origen UPDATE cuentas SET saldo = saldo + 100 WHERE id = 2; -- suma al compte destí COMMIT; -- confirma tots dos alhora
Si el sistema cau entre els dos UPDATE, l'atomicitat assegura que cap dels dos no s'aplica: els diners mai no "desapareixen". Aquesta garantia és indispensable en banca, comptabilitat o assegurances.
BASE (freqüent en NoSQL distribuït) és l'enfocament oposat, pensat per a sistemes que prioritzen la disponibilitat a gran escala:
- Basically Available: el sistema sempre respon, encara que sigui amb dades una mica antigues.
- Soft state: l'estat pot canviar amb el temps sense noves escriptures (per la propagació entre nodes).
- Eventually consistent: si deixen d'arribar escriptures, tots els nodes acabaran convergint al mateix valor, però durant un breu interval poden diferir.
L'elecció entre ACID i BASE està lligada al teorema CAP (vist al Mòdul 4): davant d'una partició de xarxa, un sistema distribuït ha de triar entre consistència i disponibilitat. ACID tendeix a privilegiar la consistència; BASE, la disponibilitat.
- Taula comparativa SQL vs NoSQL
| Aspecte | SQL (relacional) | NoSQL (genèric) |
|---|---|---|
| Model de dades | Taules amb esquema fix | Documents, clau-valor, columnes o grafs |
| Esquema | Rígid, definit abans | Flexible, dinàmic |
| Relacions | JOIN i integritat referencial |
Desnormalització / incrustació |
| Transaccions | ACID completes | Sovint BASE / ACID limitat |
| Escalat | Principalment vertical | Horitzontal natiu |
| Llenguatge | SQL estàndard | Variat segons el motor |
| Consultes ad hoc | Excel·lent | Limitat (depèn del disseny previ) |
| Millor per a | Dades estructurades amb regles fortes | Gran volum, alta escala, esquema canviant |
- Criteris d'elecció i antipatrons
No triïs per moda. Fes-te aquestes preguntes:
- Les teves dades tenen relacions complexes i regles d'integritat fortes? → SQL.
- Necessites consultes ad hoc impredictibles? → SQL (els
JOINet salven). - Tens un patró d'accés molt conegut i un volum enorme? → NoSQL dissenyat a mida d'aquest patró.
- L'esquema evoluciona constantment i les dades són semiestructurades? → documental.
- El que és crític són les relacions (recorreguts profunds)? → graf.
- Necessites accessos ultraràpids per clau (sessions, caché)? → clau-valor.
Errors habituals i consells
- Triar NoSQL "perquè escala" sense tenir problema d'escala. La majoria d'aplicacions mai no assoleixen el volum on l'escalat horitzontal compensa la pèrdua de
JOINi transaccions. Comença per SQL tret que tinguis una raó clara. - Modelar un document com si fos una taula. Si en NoSQL documental acabes fent "JOIN a mà" al codi, has triat malament el model o el disseny del document.
- Creure que NoSQL no té esquema. Sí que en té, només que viu al teu codi en lloc de a la base. Això trasllada la responsabilitat de validació a l'aplicació.
- Assumir que la "eventual consistency" és inofensiva. En un saldo bancari o un estoc, llegir una dada obsoleta pot ser un error greu. Coneix els teus requisits de consistència.
- Consell: mesura abans de migrar. Un índex ben posat en SQL resol moltíssims problemes de rendiment atribuïts erròniament al "model relacional".
Exercicis
Exercici 1. Tens una aplicació de banca que registra moviments de comptes i ha de garantir que mai no es perdin ni es dupliquin diners. Quin dels dos, SQL o NoSQL? Justifica-ho amb dues propietats concretes.
Exercici 2. Dissenya, en JSON, un document per a un perfil d'usuari d'una xarxa social que inclogui les seves dades bàsiques i una llista de les seves tres darreres publicacions incrustades. Indica quin problema de manteniment introdueixes en incrustar les publicacions.
Exercici 3. Per a un catàleg de productes on cada categoria té atributs completament diferents (un llibre té "autor", un televisor té "polzades"), quina família de base de dades encaixa millor i per què?
Solucions
Solució 1. SQL relacional amb transaccions ACID. Raons: l'atomicitat garanteix que un moviment (càrrec + abonament) s'apliqui sencer o no s'apliqui, i la durabilitat assegura que un cop confirmat sobreviu a una caiguda. A més, la integritat referencial i les restriccions CHECK eviten estats invàlids com saldos negatius no permesos.
Solució 2. Document d'exemple:
{
"_id": "usr_77",
"nombre": "Marc Riera",
"bio": "Aficionado a la fotografía",
"publicaciones_recientes": [
{ "id": "pub_901", "texto": "¡Buenos días!", "likes": 12 },
{ "id": "pub_900", "texto": "Foto del atardecer", "likes": 48 }
]
}Problema de manteniment: les publicacions estan duplicades. Si una publicació s'edita o canvia el seu nombre de likes, cal actualitzar-la tant a la seva col·lecció original com dins de cada document d'usuari que la incrusti, amb risc d'incoherències.
Solució 3. Una base documental. El seu esquema flexible permet que cada producte tingui exactament els atributs de la seva categoria sense columnes buides ni taules separades per tipus, cosa que en SQL obligaria a esquemes EAV incòmodes o a moltes taules.
Conclusió
Has après que SQL i NoSQL no són rivals, sinó eines amb compromisos diferents: SQL aporta esquema fort, JOIN flexibles i garanties ACID; NoSQL aporta esquema flexible, escalat horitzontal i, a canvi, sol relaxar la consistència (BASE). Coneixes les quatre famílies NoSQL i un conjunt de criteris per decidir, recordant que moltes arquitectures modernes adopten persistència poliglota (fer servir l'eina adequada per a cada necessitat). Un cop decidit on desar les dades, la següent pregunta és com estructurar el codi que hi accedeix sense embrutar la lògica de negoci. Això ho veurem a la propera lliçó: Patrons d'accés a dades: Repository, Unit of Work i DAO.
Curs d'Arquitectura d'Aplicacions
Mòdul 1: Fonaments de l'Arquitectura d'Aplicacions
- Què és l'Arquitectura d'Aplicacions?
- El Rol de l'Arquitecte de Programari
- Atributs de Qualitat i Requisits No Funcionals
- Decisions Arquitectòniques i Compromisos (Trade-offs)
- Documentació d'Arquitectura: Vistes i el Model C4
Mòdul 2: Principis i Tàctiques de Disseny
- Acoblament, Cohesió i Separació de Responsabilitats
- Principis SOLID Aplicats a l'Arquitectura
- DRY, KISS, YAGNI i Altres Principis de Disseny
- Tàctiques Arquitectòniques per als Atributs de Qualitat
- Gestió del Deute Tècnic
Mòdul 3: Estils i Patrons Arquitectònics
- Arquitectura Monolítica
- Arquitectura en Capes (N-Tier)
- Arquitectura Client-Servidor
- Arquitectura Hexagonal (Ports i Adaptadors)
- Arquitectura Neta i Ceba (Clean & Onion)
Mòdul 4: Arquitectures Distribuïdes i Microserveis
- Introducció als Sistemes Distribuïts
- Arquitectura de Microserveis
- Descomposició de Serveis i Bounded Contexts
- API Gateway, Service Discovery i Comunicació entre Serveis
- Patrons de Resiliència: Circuit Breaker, Retry i Bulkhead
- El Teorema CAP i la Consistència de Dades
Mòdul 5: Arquitectures Dirigides per Esdeveniments i Missatgeria
- Fonaments de l'Arquitectura Orientada a Esdeveniments
- Missatgeria Asíncrona: Cues i Brokers
- Patrons d'Esdeveniments: Event Sourcing i CQRS
- Gestió de Transaccions Distribuïdes: Patró Saga
- Streaming de Dades en Temps Real
Mòdul 6: Disseny Dirigit pel Domini (DDD)
- Conceptes Fonamentals del DDD
- Disseny Estratègic: Bounded Contexts i Llenguatge Ubic
- Disseny Tàctic: Entitats, Agregats i Repositoris
- Mapatge de Contextos (Context Mapping)
Mòdul 7: Dades i Persistència
- Estratègies de Persistència: SQL vs NoSQL
- Patrons d'Accés a Dades: Repository, Unit of Work i DAO
- Base de Dades per Servei i Gestió de Dades Distribuïdes
- Cau i Estratègies d'Invalidació
Mòdul 8: Arquitectura al Núvol i Desplegament
- Fonaments del Cloud Computing (IaaS, PaaS, SaaS)
- Contenidors i Orquestració amb Docker i Kubernetes
- Arquitectura Serverless
- Patrons de Disseny Cloud-Native
- Infraestructura com a Codi (IaC)
Mòdul 9: Qualitat, Seguretat i Observabilitat
- Escalabilitat: Horitzontal vs Vertical i Balanceig de Càrrega
- Alta Disponibilitat i Tolerància a Fallades
- Seguretat per Disseny i Autenticació/Autorització
- Observabilitat: Logging, Mètriques i Traçabilitat
- Rendiment i Proves de Càrrega
