Nel precedente articolo abbiamo visto a grandi linee le differenze sostanziali tra SQL e NoSQL, tuttavia NoSQL di per sé è un mondo sconfinato.
I vari motori NoSQL si differenziano soprattutto per il modo in cui immagazzinano i dati e, conseguentemente, come li presentano all’utente.
I tipi più comuni di NoSQL sono sostanzialmente 4:
- Orientati alle colonne (column-oriented)
- Orientati ai documenti (Document Store)
- A coppie chiave-valore (Key Value Store)
- A grafo (Graph)
Orientati alle colonne
Come il nome stesso ci suggerisce, a differenza dei classici database relazionali, in questo tipo di database l’informazione è salvata per colonna.
Prendiamo come esempio la tabella:
AutoreID | Nome | Cognome |
---|---|---|
42 | Nico | Caprioli |
666 | Andrea Simone | Costa |
8080 | Dario | Frongillo |
Trascurando eventuali ottimizzazioni, in un clasico database relazionale i dati verrebbero serializzati come:
42;Nico;Caprioli 666;Andra Simone;Costa 8080;Dario;Frongillo
Nei database orientati alle colonne invece si avrebbe:
42;666;8080 Nico;Andrea Simone;Dario Caprioli;Costa;Frongillo
Questo modo di gestire i dati porta vantaggi nel caso di tabelle il cui numero di colonne varia nel tempo, permettendo una modellazione banale di nuove specifiche non previste nel progetto iniziale.
In particolare questo tipo di database trova largo utilizzo in sistemi OLAP, dove utilizzare un sottoinsieme delle colonne è pane quotidiano.
Infine una nota di merito va a quelle funzioni come il calcolo del minimo o del massimo: dal momento che i dati sono immagazinati per colonne, l’aumento di performance è notevole.
Tra i maggiori esponenti di questa tipologia di database troviamo:
- Apache Cassandra
- Apache HBase
- Google BigTable
Orientati ai documenti
In questa categoria rientrano i database che permettono la manipolazione di dati semi-strutturati.
In genere questi database usano una rappresentazione interna che può variare tra XML, JSON, BSON o YAML e in genere forniscono un accesso tramite REST API o con protocolli di interoperabilità tra linguaggi come Apache Thrift o gRPC.
Volendo fare un confronto con i database relazionali, possiamo affermare che un documento corrisponde ad una riga; tuttavia questo documento, a differenza della riga, può non avere uno schema preciso. Riprendendo l’esempio precedente, potremmo avere una situazione del genere:
{ id: 42, nome: "Nico", cognome: "Caprioli", autore_di_questo_articolo: true }, { id: 666, nome: "Andrea Simone", cognome: "Costa" }
L’esempio è decisamente idiota, ma rende chiaro un concetto: sebbene i due documenti si assomiglino, uno porta un valore aggiunto rispetto all’altro.
Nel secondo caso, venendo da una tradizione SQL, si potrebbe pensare che autore_di_questo_articolo
sia un valore nullo. In realtà tale valore non esiste affatto, non è allocato in memoria spazio per contenerlo. Per chiunque sia minimamente familiare con JSON, il prossimo passo dei database orientati ai documenti è banale: il tipo di dato di un elemento all’interno del documento, a differenza di SQL non deve necessariamente essere un tipo primitivo. È piuttosto comune difatti ritrovarsi con elementi che sono oggetti o liste, a loro volta contenenti altri oggetti e così via. La nidificazione è possibile con questi tipo di database e ne rappresenta uno dei punti di forza maggiore, in quanto permette una flessibilità inarrivabile da SQL. È importante notare che, sebbene questi database siano senza schema, è possibile definire degli indici. Tra i maggiori esponenti di questa tipologia di database troviamo:
- BaseX
- MongoDB
- CouchDB
Coppie chiave-valore
I database di tipo chiave-valore sono particolarmente affini a quelli orientati ai documenti, infatti come questi ultimi non richiedono l’esistenza di uno schema e allo stesso modo, si associa a una data chiave, un determinato valore.
La differenza sostanziale tra i database chiave-valore e quelli orientati ai documenti risiede nel modo in cui le chiavi vengono gestite, infatti si hanno due punti in cui le due soluzioni divergono:
- La chiave deve sempre essere specificata
- I valori associati ad una chiave non possono essere indicizzati né è possibile interrogarli, pertanto sono opachi dal punto di vista del database
Volendo fare un paragone con le strutture dati tipiche di un qualsiasi linguaggio di programmazione, si potrebbe dire che i database di tipo chiave-valore sono equivalenti ad una Hash Table.
Date le restrizioni poste in essere sulle chiavi e sull’opacità dei valori, è evidente che questi database siano ottimizzati per l’interrogazioni sulle chiavi. Non è raro infatti trovarsi in situazioni in cui le chiavi siano generate in modo intelligente, ad esempio tramite un UUID, utilizzando poi il database come cache.
Dal momento che questi database tendono ad essere in-memory per avere le migliori performance possibili, non è strano scoprire che sono in grado di rispondere a decine di migliaia di richieste al secondo[1]. È di dovere precisare che, sebbene i valori siano opachi, alcuni database forniscono un meccanismo per identificare il tipo di dato ed operarci di conseguenza. Alcuni tipi di dati potrebbero essere, oltre ai classici scalari, stringhe, set (sia ordinati che non ordinati) o liste.Ritornando al nostro classico esempio:
42: "Nico Caprioli" 666: ["Andrea Simone Costa", "non sa il JS"]
Tra i più popolari troviamo:
-
- Redis
- Memcached
- Voldemort
Grafi
Come suggerisce il nome, nei database a grafo le entità sono rappresentate da nodi di un grafo, collegati tra loro tramite relazioni.
Questi tipi di database trovano piena utilità in quei contesti in cui la relazione tra entità è il dato importante e porta con sé informazioni, come ad esempio relazioni sociali tra persone, trasporti o topologie di rete. Vien da sé che questi tipi di database hanno un contesto applicativo piuttosto ristretto e facilmente identificabile in fase di design, non è tuttavia raro che i dati di per sé vengano memorizzati in un database orientato ai documenti, utilizzando il grafo solo per rappresentare le relazioni.Sì capisce che l’esempio presentato fino ad ora non è applicabile in questo caso, però una valida alternativa per vedere visivamente come siano rappresentati i dati è comunque utile:
Tali database infatti forniscono operazioni native per interrogare i grafi come shortest path, o nodi ad una certa distanza dal nodo corrente. I database di questo tipo sono abbastanza rari; le soluzioni attuali sono:
-
- Neo4j
- FlockDB
Conclusioni
A questo punto, una tabella riassuntiva non può che essere comoda per la scelta del NoSQL che meglio si adatta ai propri scopi:
Proprietà | Orientato alle colonne | Orientato ai documenti | Coppie chiave-valore | A grafo |
---|---|---|---|---|
Supporto per uno schema simil-tabulare | Sì | No | No | Sì |
Update Parziale | Sì | Sì | Sì | No |
Query sul singolo valore | Sì | Sì | No | Sì |
Funzioni di aggregazione tra righe | Sì | No | No | No |
Relazioni tra entità | No | No | No | Sì |
Batch Update | Sì | Sì | Sì | No |