Confronto SQL vs NoSQL

C

Relazionale vs non relazionale, detto anche SQL vs NoSQL, è una diatriba che va avanti sin dall’alba dei tempi. Se siete arrivati fin qui, molto probabilmente anche voi vi siete trovati nel fuoco incrociato dei sostenitori di una o l’altra fazione, e avete sperato di vederci un po’ più chiaro.

Cercherò in tutti i modi di non lasciar trasparire con quale dei due mi trovi più a mio agio. Tuttavia, se leggendo questo articolo doveste avere l’impressione che abbia dato più peso ad una rappresentazione rispetto all’altra, massacratemi pure nei commenti (no kritike, solo komplimenti!) e cercherò di aggiustare il tiro!

SQL vs NoSQL

Anzitutto partiamo dalle basi: SQL, acronimo di Structured Query Language, come suggerisce il nome, è un linguaggio volto all’interrogazione di dati altamente strutturati. Sebbene esista uno standard SQL, nella realtà dei fatti chiunque abbia usato più di un motore SQL, sa bene che ognuno ha le sue peculiarità. Ciononostante, la sintassi di base resta sostanzialmente la stessa e, in fin dei conti, migrare da un engine all’altro ha un costo relativamente ridotto. Sull’altra faccia della medaglia ci sono invece i database NoSQL, dove il prefisso no significa esattamente quello che ci si aspetta: Not Only SQL. I database NoSQL nascono dunque con l’idea di rappresentare dati eterogenei, per i quali voler forzare una struttura causerebbe un numero di mal di testa al progettista non indifferente; oltre al fatto che le query che ne verrebbero fuori, una volta funzionanti, assomiglierebbero a magia nera.

A questo qualcuno starà pensando che l’universo è un posto ordinato, tutto ha una forma ben precisa ed è in relazione con il resto in modo ben definito, quindi non c’è bisogno dei NoSQL!

Qualcun altro, d’altro canto, avrà immediatamente pensato che relegarsi a vincoli stringenti di struttura diminuisce la produttività, l’universo sarà pure ordinato, ma quello che sta nella mente dei nostri clienti no, e cambia da un giorno all’altro!

A entrambi voglio dare ragione: ambedue le argomentazioni sono ineccepibili, ed è qui che inizia veramente l’articolo:

Non esiste un meglio o un peggio tra SQL e NoSQL, esiste solo il più adatto ad una determinata circostanza.

Transazioni

Uno dei punti di forza dei database relazionali sono le transazioni, delle quali i database non relazionali sono in genere sprovvisti. Per essere definite tali, le transazioni devono rispettare le celebri proprietà ACID, ovvero:

  • Atomicity: l’intera transazione è assimilabile ad un’operazione atomica.
  • Consistency: una transazione inizia in uno stato consistente e finisce in uno stato consistente, ovvero o viene eseguita con successo, o fallisce e conseguentemente è come se nessuna delle sue operazioni fosse stata eseguita.
  • Isolation: dal momento che le transazioni vengono eseguite in parallelo, il loro scheduling deve equivalente ad una versione sequenziale.
  • Durability: una volta che una transazione è stata eseguita con successo, il risultato che ne deriva è persistente anche in caso di errori di sistema.

D’altro canto, i database non relazionali in genere garantiscono atomicità sulla singola istruzione, indipendentemente da quanto questa sia complessa. Tale Eric Brewer ha coniato il termine BASE che i database NoSQL devono rispettare:

  • Basic Availability: è garantita una risposta ad ogni richiesta, sia che sia conlusa con successo che con fallimento.
  • Soft state: lo stato del sistema può cambiare nel corso del tempo, anche senza intervento dell’utente.
  • Eventual consistency: dal momento che si ha soft state, possono verificarsi casi di mancata consistenza, la quale va gestita manualmente dallo sviluppatore.

Tutto ciò rende evidente che ogni tal volta sia necessario rappresentare su un database un concetto del mondo reale che contiene la parola transazione, a meno di essere pazzi suicidi che vogliono implementare un loro meccanismo di gestione delle transazioni a mano, la scelta ricade necessariamente sui database relazionali.

Performance

L’ultima risorsa dei fan-boy del non relazionale consiste nell’asserire a spada tratta che i NoSQL sono più veloci, quindi è bene usarli perché l’utente vuole un sistema estremamente reattivo.

Per certi versi non hanno torto, in innumerevoli casi i NoSQL sono più veloci della loro controparte. Tuttavia, questa non è certo una verità assoluta, ed ha senso solo nel momento in cui si usano i database NoSQL per quello per cui sono progettati.

Il succo della questione quindi è che, sì: i NoSQL sono tendenzialmente più veloci, ma alla fine il grosso lo fa il progetto del database. Non ci dobbiamo certo stupire se un SQL ben progettato sia più veloce di un NoSQL progettato dal cuggino.

Cache

Il discorso cambia radicalmente quando un database NoSQL viene utilizzato come cache. Lo standard in questo settore è un datastore di tipo chiave-valore denominato Redis che non ha rivali in questioni di velocità. In una situazione del genere, voler usare un database SQL sarebbe follia. Quello che invece succede è che viene messo Redis (o equivalente) tra il database (che sia SQL o NoSQL non importa) e l’applicativo, così da velocizzare di diversi ordini di grandezza le operazioni eseguite più di frequente.

Normalizzazione dei dati

Uno dei punti cardine dei database SQL, nonché uno dei maggiori vincoli, consiste nella normalizzazione dei dati. Lo scopo di questo vincolo è quello di ridurre la ridondanza dei dati e consente controlli di integrità sui dati. Quanto appena detto rappresenta certamente un vantaggio; tuttavia, come tutti sappiamo, comporta anche uno svantaggio immenso: i join. Data una lista di attributi, in SQL si presenta la necessità di creare una tabella di relazione che permetta di collegare una determinata entità ai figli. Con i database NoSQL questa necessità viene meno in quanto, non richiedendo uno schema definito a priori, supportano nativamente liste e, in senso più lato, entità annidate; pertanto non è raro trovare un’entità che tra i vari attributi, ne ha uno che è un’entità a sua volta.

Tuttavia, la denormalizzazione va usata con estrema cautela. Avere dati non normalizzati porta con estrema semplicità alla duplicazione degli stessi. La duplicazione è senza dubbio vantaggiosa da un punto di vista di velocità di accesso, ma si porta dietro delle problematiche non trascurabili.

Anzitutto lo spazio su disco richiesto dal database; questo problema comunque, dato il costo delle unità di memorizzazione può essere parzialmente ignorato. Secondo poi, l’integrità dei dati. Nel caso in cui si voglia aggiornare una qualsiasi entità duplicata, diventa cruciale aggiornare ogni singola copia del dato stesso; a seconda delle circostanze, l’operazione può essere non banale. Proprio data la difficoltà di gestione di situazioni simili, si hanno sempre più database NoSQL con supporto ai riferimenti, che altro non sono che le relazioni.

Quando usare cosa

Arrivati a questo punto vi sarete di certo fatti un quadro generale, ma è bene rimarcare in quali contesti è preferibile usare una soluzione piuttosto che l’altra.

I database relazionali trovano spazio d’applicazione quando si ha a che fare con dati strutturati, ovvero quando è facile creare una rappresentazione su tabella semplice e lineare, con un numero ridotto di relazioni. Inoltre, gli SQL sono praticamente obbligatori ogni volta che dobbiamo garantire integrità sui dati e le proprietà ACID in senso lato.

Contrariamente, i NoSQL sono estremamente versatili e quindi indicati in quelle situazioni in cui dobbiamo modellare il polimorfismo. Se si hanno entità tra loro tutte simili e che grossomodo portano la stessa informazione, ma con piccole differenze l’una dall’altra, con NoSQL il problema si risolve qualche manciata di minuti. In SQL, invece, è necessaria una soluzione decisamente più complessa. Un possibile approccio è quello di creare una tabella differente per ognuna delle entità. Alternativamente si potrebbe creare un’immensa tabella con tutti i possibili attributi tra tutte le entità, ma per la maggioranza nullabili. In entrambi i casi, comunque, il risultato sarebbe lo scorrimento veloce del calendario (a patto che riporti le santità di ogni giorno!) ed una scalabilità pressoché inesistente.

NoSQL è quindi ideale nel caso di dati abbastanza scorrelati e che tendono ad evolvere nel tempo; l’assenza di una struttura fissa permette di aggiungere nuovi tipi di dati (o modificare gli esistenti) senza dover mettere mano al database.

A proposito di me

Nico Caprioli

Si diletta con i computer sin dall'età di 8 anni, per sbarcare nel mondo della programmazione durante il liceo.
Dopo una laurea magistrale in Ingegneria Informatica, passa le sue giornate a battere i tasti sperando di scrivere codice C# valido.

Gli articoli più letti

Articoli recenti

Commenti recenti