Capitolo 1

Join, Transaction e Pre-Join


Capitolo 1: Introduzione e Basi


Introduzione database no-SQL
Join, Transaction e Pre-Join
MongoDB in un'App
Come installare MongoDB
JSON e BSON
Schema Dinamico
Da Relazionale ai Documenti
Schema Design

Join, Transaction e Pre-Join

Capiremo perché mancano le Join e le Transaction su MongoDB e vedremo qual'è l'alternativa che ci offre, ovvero le Pre-Join.

Join e transaction in un ambiente distributo

Abbiamo detto che MongoDB non supporta né joins e né transactions e questo è considerato qualcosa di inconcepibile da chi viene dai database relazionali, cerchiamo di fare chiarezza e vediamo perché effettivamente non le supporta. Facciamo uno sforzo di fantasia e proviamo ad immaginare come distribuire il nostro database classico, con tabelle e tutto il resto, in un ambiente distribuito, ossia in un insieme di server collegati tra loro.

La prima domanda che sorge spontanea è: con quale criterio distribuisco le mie tabelle nei vari server? E come faccio a fare le joins una volta che queste sono distribuite?

Qualcuno potrebbe rispondere in modo classico: “mettendo tutte le tabelle in tutti i server così da supportare le joins”, ma questo in realtà non realmente è scalabile.

Qualcun altro potrebbe pensare di dividere la tabella più grande su più server e quelle più piccole copiarle in tutti i server, tanto sono piccole...un po’ come lo star schema. È vero, è una soluzione scalabile e supporta le joins, ma c’è un piccolo problema: lo star schema parte dal presupposto che abbiamo un’unica tabella grande ma, questo non è applicabile a tutte le situazioni, noi possiamo avere più tabelle grandi da voler dividere, quindi lo star schema non è applicabile.


Dividendo le varie tabelle sui servers dobbiamo ricordarci che una query di join molto probabilmente coinvolgerà più server, quindi i tempi di attesa per avere un risultato aumenteranno. Se quando effettuo una join le tabelle che vado a richiamare sono distribuite solo su due server può andarmi anche bene, e magari la query risulta veloce, ma dal momento che, siamo in un sistema scalabile posso avere 2 come posso avere 20 o 30 servers coinvolti! E in questi casi avremo dei tempi d’attesa secolari.

Se con le join c’è qualche difficoltà proviamo a pensare a quei rari casi in cui usiamo le transactions, sono sicuramente utili ma immaginiamocele in un ambiente distribuito, dobbiamo considerare gli eventi di commit e rollbak in tutti i server coinvolti senza dimenticarci che sono soggette alle proprietà ACID (Atomicity, Consistency, Isolation, Durability).

Ah mi raccomando occhio ai tempi di attesa! Nessuno vuole un database con delle pessime performance!


Insomma diventa veramente molto complicato implementare joins e transactions in un ambiente distribuito, questo però non è un problema solo di Mongo ma bensì di tutti i database che vogliono essere realmente scalabili.

Mi piace pensare che tra Dwuit ed Eliot ci sia stata una conversazione di questo tipo e che abbiano scelto molto semplicemente di usare un altro approccio ai dati.


Abbiamo visto che ci sono dei reali problemi pratici nell’applicare queste due funzionalità in un ambiente distribuito e MongoDB non può di certo rinunciare alla scalabilità dato che è il suo primo obiettivo, quindi ha dovuto per forza rinunciare a queste due funzionalità.

Però immaginarsi un database senza joins non è cosi semplice, quindi cerchiamo di capire qual è stato l’approccio di Mongo per creare comunque un qualcosa di utile e potente.


Un nuovo approccio

Pensiamo all’ambiente relazionale, le joins sono essenziali e senza è impossibile creare qualcosa di meglio quindi dobbiamo sicuramente cambiare l’approccio: ci serve qualcosa che sia potente, agile e flessibile!


Ci sarebbero i key value store, con set e get, però serve qualcosa di più come ad esempio il Document Oriented in cui i singoli record sono memorizzati come documenti. Precisiamo cosa si intende con Documento perchè spesso si crea confusione, il termine documento si utilizza quando si parla di database ed equivale ad un oggetto della programmazione ad oggetti, quindi dire oggetto e dire documento in realtà è la stessa cosa.

Abbiamo, così, una corrispondenza diretta tra la programmazione ad oggetti e i dati presenti nel database che rende il Document Oriented agile e flessibile cosicché le aziende possano adattarsi ai cambiamenti più velocemente.


Ora ci manca solo la codifica ed è ovviamente il JSON! È familiare, nel senso che è umanamente leggibile al contrario dell’XML, è una codifica indipendente e ha il suo standard.

Adesso abbiamo tutto quello che ci serve per risolvere il problema delle joins, ovvero le pre-join o embedding, o incapsulazione, o denormalizzazione...chiamatelo come volete!


Essenzialmente il concetto è questo: quando noi effettuiamo una join tra due tabelle ci aspettiamo che i dati vengano uniti in un unico risultato e fin qui è semplice. Le pre-join usano il processo inverso, partono dal risultato già unito cioè: già prima di salvare nel database il nostro dato noi includiamo al suo interno anche altre informazioni, un po’ come se fosse il risultato di una join.


Qualcuno ha capito? Forse spiegato in questo modo risulta un po’ confusionario anche se in realtà è veramente semplice, meglio vedere subito un esempio pratico.


Pre-Join in pratica

Immaginiamo di essere in un database relazionale e di avere due tabelle: clienti e veicoli.

Nella tabella cliente ogni riga è un cliente con il suo ID, mentre nella tabella veicoli abbiamo la lista di vari veicoli di diverse marche e una chiave esterna per identificarne il proprietario. Con una normale join possiamo ottenere tutti i veicoli per ogni cliente.


Vediamo ora cosa ci propone Mongo. Non avendo le joins dobbiamo unire le informazioni già prima di salvare il dato nel database, proviamo a fare l’esempio di Alberto: creiamo un nuovo documento, copiamo i dati cliente (Alberto, Olla, ecc.), adesso dobbiamo includere i dati dei veicoli di Alberto al suo interno quindi creiamo un array di oggetti dove ogni oggetto è un diverso veicolo, mettiamo la Smart, la Ferrari, ognuno con i suoi attributi. In Mongo non ci servirà più la tabella veicoli perché quelle informazioni saranno incluse in quelle di ogni proprietario.


Guardate com’è molto più leggibile, è diventato immediato! Abbiamo unito i dati di due tabelle all’interno di un solo documento che contiene tutte le informazioni che vogliamo.


Nel documento di Alberto possiamo aggiungere tutto quello che ci pare, ad esempio un punto gps utile per le query geospaziali, ovviamente se volessimo inserire un altro cliente, come Marta, dovremo creare un nuovo documento che avrà una struttura del tutto simile a questa.


Questo approccio è veramente figo e assicura a Mongo delle ottime performance, con una semplice query di selezione otteniamo gli stessi risultati che avremmo con una join relazionale!

Una vera figata e l’abbiamo soltanto introdotto! Ci sarebbe da dire in quali casi è consigliabile utilizzarlo e soprattutto con quale criterio va applicato ma è meglio rimandare questi argomenti a delle lezioni successive.