Model NoSQL
Model NoSQL
Un dels reptes clàssics del model relacional és la distribució d’una BBDD en diferents servidors per raó de mida i rendiment (clústers), mantenint l’accés com si fos una sola.
El funcionament en clústers utilitza dues idees:
- La replicació: repliquem les dades en master-slave o peer-to-peer.
- El sharding: situem diferents parts de les dades en diferents servidors.
Les BBDD relacionals no van ser dissenyades originàriament per a funcionar de forma distribuïda, i garantir ACID entre shards és costós (tot i que solucions com Postgres/Citus, Vitess o Aurora ho fan possible). Aquesta és una de les motivacions principals per a migrar a NoSQL. Una altra és la productivitat en el desenvolupament d’aplicacions, ja que la interacció amb les dades sovint és més còmoda.
Un model agregat és una col·lecció de dades amb les quals interactuem com a una unitat. Els models agregats permeten treballar més fàcilment amb clústers, agafant l’agregació com a unitat de replicació i sharding. A més, l’agregació també facilita la feina dels desenvolupadors, perquè la manipulació de dades es produeix molt sovint a nivell de agregat.
Els tipus principals de BBDD NoSQL són els models agregats (key-value, document i column) i els de graf.
Key-Value
És la forma més simple d’agregació. Contenen col·leccions de parelles clau-valor, com els diccionaris o les taules hash. La clau és l’identificador i les dades poden ser un objecte JSON, un blob binari o un altre tipus.
| Key | Value |
|---|---|
| “user:1” | { “name”: “Alice”, “age”: 25 } |
| “user:2” | { “name”: “Bob”, “age”: 30 } |
S’utilitzen per a fer caching, gestió de sessions o mètriques senzilles. Són molt fàcils d’implementar, eficients i escalables. Però no permeten fer queries gaire complexes.
Exemples populars: Redis, Amazon DynamoDB (mode key-value).
Document
Les dades s’organitzen el documents de format JSON, BSON o XML. Tenen una estructura jeràrquica, que els atorga flexibilitat. Un document és una unitat atòmica que pot ser consultada, modificada o esborrada. És una entitat que freqüentment té les dades relacionades al mateix document.
Per exemple, aquest seria un usuari amb les ordres associades. No cal predefinir les seves columnes, ni fer queries per trobar les ordres de l’usuari:
{
"_id": "user:1",
"name": "Alice",
"age": 25,
"orders": [
{ "orderId": "A100", "amount": 50.5 },
{ "orderId": "A101", "amount": 25.0 }
]
}
Les queries permeten fer filtratge, agregació o indexació. Per exemple:
- Trobar usuaris més grans de 20:
{ "age": { "$gt": 20 } } - Obtenir una certa ordre:
{ "orders.orderId": "A100" }
Aquest tipus de model permet esquemes flexibles, dades jeràrquiques i també camps indexables per a fer queries més ràpides. Són molt flexibles per no tenir esquema, però l’organització pot portar duplicacions. Les relacions entre documents són possibles (via referències o operacions com $lookup a MongoDB), però no s’apliquen automàticament: no hi ha foreign keys, i la integritat referencial recau a l’aplicació.
Es poden utilitzar a gestors de continguts, llocs d’e-commerce o per fer event logging.
Exemples populars: MongoDB, Couchbase, Amazon DocumentDB.
Wide-Column (Column-Family)
Aquest model, de vegades anomenat wide-column o column-family, organitza les dades com a tuples disperses (row key, column key) → value. Cada fila té una clau única i pot contenir un conjunt arbitrari de columnes (potencialment milers), diferent per fila. Les columnes s’agrupen en famílies, que defineixen com s’emmagatzemen físicament i permeten optimitzar els patrons d’accés.
A diferència d’una taula relacional, no totes les files tenen les mateixes columnes; és una estructura dispersa. Per exemple:
| Row Key | name | age | order:A100 | order:A101 | order:A102 |
|---|---|---|---|---|---|
| user:1 | Alice | 25 | 50.5 | 25.0 | |
| user:2 | Bob | 30 | 75.0 |
Cassandra exposa un llenguatge (CQL) amb sintaxi semblant a SQL que presenta les dades de forma tabular, però internament es tracta de files particionades amb columnes dinàmiques.
S’utilitzen per a emmagatzemar esdeveniments amb timestamps, sèries temporals o datasets molt grans amb dades disperses. Permeten operacions d’escriptura intensives, però el modelatge requereix pensar les queries per endavant (el disseny es fa query-first).
Exemples populars: Apache Cassandra, HBase, ScyllaDB.
Graf
Els models de graf representen les dades com a nodes (entitats) connectats per arestes (relacions), on tant els nodes com les arestes poden tenir propietats. A diferència dels models agregats, aquí la relació és una ciutadana de primera classe: recórrer connexions és barat i expressiu.
Convé dir que els grafs són un membre atípic de la família NoSQL: s’hi inclouen per convenció i per raons històriques, però no comparteixen les motivacions centrals de la resta (escalat horitzontal en clústers, orientació a agregats, consistència eventual). De fet, molts SGBD de graf ofereixen transaccions ACID completes i són difícils de partir (sharding), ja que les relacions travessen tot el graf.
Per exemple, en una xarxa social: un node Persona connectat mitjançant arestes AMIC_DE, TREBALLA_A o VIU_A amb altres nodes Persona, Empresa o Ciutat.
Són especialment útils en dominis on les relacions són el que aporta valor: xarxes socials, sistemes de recomanació, detecció de frau, grafs de coneixement o anàlisi d’infraestructura. Les queries (en llenguatges com Cypher o Gremlin) permeten expressar recorreguts complexos que en SQL requeririen múltiples joins.
Exemples populars: Neo4j, Amazon Neptune, ArangoDB.
Consistència i el teorema CAP
El teorema CAP afirma que un sistema distribuït només pot garantir simultàniament dues de les tres propietats següents:
- Consistency: totes les lectures veuen l’última escriptura.
- Availability: tota petició rep una resposta (encara que no sigui l’última versió).
- Partition tolerance: el sistema continua funcionant tot i que la xarxa entre nodes falli.
Com que les particions de xarxa són inevitables en un sistema distribuït real, a la pràctica la tria és entre CP (sacrificar disponibilitat per mantenir consistència) i AP (sacrificar consistència per mantenir disponibilitat).
Moltes BBDD NoSQL trien AP amb consistència eventual: les escriptures es propaguen asíncronament i, durant un temps, diferents nodes poden retornar valors diferents, però convergeixen. Altres (com MongoDB amb certes configuracions, o HBase) ofereixen consistència forta a costa de disponibilitat en cas de partició. No és un guany gratuït: és un compromís que cal triar segons el cas d’ús.
Comparativa
| Funcionalitat | Key-Value | Document | Wide-Column | Graf |
|---|---|---|---|---|
| Estructura | Parelles Key-Value | Documents JSON/BSON/XML | Files disperses amb columnes dinàmiques | Nodes i arestes amb propietats |
| Consultes | Només per clau | Per camp, consultes niades | Per clau de fila, rang de columna | Recorreguts (Cypher, Gremlin) |
| Casos d’ús | Caching, cerques ràpides | Esquemes flexibles, dades jeràrquiques | Sèries temporals, escriptures massives | Xarxes socials, recomanacions, frau |
| Flexibilitat d’esquema | Senzilla | Alta | Moderada | Alta |
| Consistència típica | Eventual (configurable) | Configurable | Eventual (ajustable per query) | Forta |