Capitolo 1

Schema Design


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

Schema Design

Come strutturare un database su MongoDB per migliorare le performance in lettura, parliamo di schema design.

Quando effettuare l'embedding?

Le pre-join o embedding possono essere potentissime se usate nel modo giusto e d’altra parte per chi non ne comprende l’approccio possono essere completamente inutili, come ad esempio quelli che cercano di usare MongoDB ricreando pari pari la struttura di un database relazionale.

Quindi quando è meglio usarle e quando no? In quali casi e come? Se sappiamo questo anzi se capiamo questo possiamo creare delle soluzioni personalizzate e ultra performanti.

Quindi, cerchiamo di capire in quali casi è consigliabile usarle e perchè.


Riprendiamo l’esempio della lezione precedente, vi ricordate? Avevamo una collection per gli articoli con tag e commenti.


Per i tags potrebbero sorgere alcune criticità come ad esempio il problema delle ripetizioni, potremo avere molti tag duplicati, ovviamente con pochi articoli è irrilevante ma dobbiamo sempre pensare di avere tanti articoli. Se in tutti gli articoli fosse presente uno stesso tag bello lungo avremo una ripetizione e quindi spazio occupato inutilmente dalla stessa informazione. L’alternativa sarebbe usare degli indici numerici per ognuno, in questo modo proprio quel tag così lungo (ad esempio 64caratteri) sarebbe stato un 1 o un 100.

Un altro problema potrebbe essere che avendoli cosi sfusi non possiamo avere un controllo immediato. Immaginiamo di voler sostituire un tag, per un errore di battitura o semplicemente ci siamo accorti che era meglio un altro termine, per farlo dobbiamo fare un replace su ogni documento che ha quel tag; invece con gli indici ci sarebbe bastato modificare il valore una sola volta.


Se usassimo gli indici, però, le performance verrebbero influenzate negativamente, quindi come facciamo? Ci accontentiamo, meglio avere una lettura veloce anche se con dei tag duplicati. Anche il replace non rappresenta un grosso problema dato che la modifica dei tag è un operazione poco frequente, ovviamente rimane sempre possibile sostituirli in modo meno immediato.


Diciamo che la nostra scelta di usare l’embedding è comunque valida perchè è molto raro accedere solo ai tag di un singolo post senza accedere anche al post stesso e lo stesso vale per la lettura dei commenti.


Capire meglio questo concetto è fondamentale e fa un enorme differenza quando si deve strutturare un database, quindi cerchiamo di spiegarlo meglio.

È importante capire quando fare o non fare l’embedding e per farlo ci basta seguire una semplice regola:
“Se il flusso d’accesso ai dati seguirai, l’embedding non sbaglierai”

Vi starete chiedendo cos’è il flusso d’accesso ai dati, in realtà l’abbiamo già usato senza saperlo.


Immaginiamo di dover caricare la pagina in cui viene mostrato un singolo post, ci servono le sue informazioni quindi: titolo, testo, e autore, di solito alla fine dell’articolo troviamo anche i commenti quindi li mostriamo e ovviamente mostriamo anche i tags o categorie dell’articolo.

Proviamo ad individuare il flusso di accesso ai dati, come prima cosa ci servono i dati del post, poi la lista dei commenti ed infine i tag.

Tener conto del flusso d’accesso ai dati quando si struttura un database assicura delle ottime performance.


Quindi possiamo dire che, quando accediamo ai dati di un Post solitamente dobbiamo accedere nello stesso momento sia ai commenti sia ai tags. Quando si verifica questa situazione ha senso fare l’embedding perché fa tutto parte dello stesso flusso d’accesso.


Un’altra cosa molto importante da considerare è il limite di 16 MB su ogni documento. Non possiamo mai superare questa soglia, ovviamente non parliamo di sorgenti di immagini o simili che possiamo salvare con una diversa configurazione ma parliamo di normali documenti come tutti quelli che abbiamo visto sinora.

Se pensate di superare questo limite, magari a causa dei commenti, non potete usare l’embedding ma dovete appoggiarvi ad una collection separata.

Non spaventatevi, per siti normali non c’è nessun pericolo, si parla di casi estremamente rari.


In breve, ricordiamoci sempre di seguire il flusso d’accesso ai dati e del limite di 16 MB per documento.

Come vi sembra? Dubbi?

Vi avevo detto che avremo visto come migliorare la struttura degli articoli, soprattutto la parte dei commenti, per rendere tutto più performante. Adesso vedremo come.

Questi esempi fighissimi li ho presi dalla seconda puntata del Webinar tenuto da Massimo Brignoli, Senior Solution Architect MongoDB, il video è su youtube ma inspiegabilmente ha appena 300 visualizzazioni eppure è in italiano e lui è bravissimo; vi lascio il link https://youtu.be/r0em6qZmYhM perché sicuramente spiega meglio del sottoscritto.

Andiamo a vedere quindi quali sono queste proposte di ottimizzazione delle performance.

Modellazione dei commenti: incapsulamento

Allora una proposta noi l’abbiamo già vista e ne abbiamo già parlato: prevede di incapsulare i commenti nel documento dell’articolo quindi abbiamo il vantaggio di ottenere tutti i dati con una sola query ma allo stesso tempo l’array che contiene i commenti non ha limiti, quindi potrebbe crescere in qualsiasi momento e superare i 16 MB.


Per ovviare a questo si potrebbe provare un altro approccio, proviamo con le reference.

Modellazione dei commenti: reference

Questo è più banale, abbiamo sempre il nostro array per i commenti ma dentro salviamo una semplice referenza quindi un l’ID di ogni singolo commento, che invece andremo a salvare in una collection separata.


In questo modo sicuramente non c’è il rischio di sforare i 16 MB ma perdiamo in termini di performance perché dobbiamo eseguire una query per il singolo articolo, ottenere la lista di tutti gli id dei commenti e solo a questo punto richiedere i commenti eseguendo una query per ognuno, insomma non è per niente ottimizzato quindi meglio andare avanti.

Modellazione dei Commenti: approccio ibrido

Collection dei Posts

Nel webinar viene proposto un approccio ibrido molto figo e super interessante: teniamo i commenti incapsulati ma li teniamo in un array a dimensione fissa, quindi incapsuliamo solo gli ultimi 20 commenti inseriti; quando andremo a fare la query per avere i dati dell’articolo possiamo già mostrare gli ultimi 20 commenti senza eseguire altre query ed essendo quello dei commenti un array a dimensione fissa non rischiamo di sforare il limite.


Per avere un array con dimensione fissa possiamo usare un particolare operatore durante l’inserimento del nuovo commento cosicché Mongo tagli gli elementi in eccesso.

Così facendo abbiamo solo gli ultimi 20 commenti a disposizione, tutti gli altri invece vengono divisi in gruppi e messi in una collection separata.


Dato che qui abbiamo solo gli ultimi 20 commenti e gli altri sono separati è consigliabile aggiungere nella nostra app un piccolo codice per il conteggio nell’inserimento e nella rimozione dei commenti stessi, così da non dover rifare ad ogni refresh gli stessi conti.


Quindi teniamo il conto del numero totale di tutti i commenti ma non solo, andiamo oltre e teniamo il conto anche del numero totale delle pagine dei commenti.

Mi spiego, immaginiamo che il nostro articolo sia un vero successone, che abbia raggiunto i 10.000 commenti...anzi no è troppo, facciamo 85! Ovviamente non li mostreremo tutti in una sola pagina, faremo una paginazione magari in gruppi di 40 come fa youtube.


Nell’articolo abbiamo 20 commenti che mostriamo subito nella pagina, se l’utente però fosse un gran curiosone e ne volesse di più allora andrebbe alla pagina successiva e solo a questo punto effettueremo la query per chiederne altri 40.

Collection dei Comments

Questa è la nostra collection per i commenti, li salviamo in gruppi quindi in differenti documenti dove ognuno ne raggruppa 40, avremo: un riferimento all’id dell’articolo, il numero della pagina di cui fanno parte e quanti commenti effettivamente contiene la pagina (sarà un intervallo tra 1 e 40).


Abbiamo costruito la struttura seguendo il flusso dei dati, abbiamo l’articolo velocissimo in lettura già con 20 commenti inclusi e abbiamo le singole pagine per i gruppi di commenti pronte ad essere visualizzate.


Praticamente rendiamo leggermente più complicata la scrittura, aggiungendo i contatori e dividendo i commenti già in gruppi, ma allo stesso tempo ottimizziamo drasticamente le performance in lettura che è poi l’operazione più frequente.

Non posso far altro che ringraziare immensamente Massimo Brignoli per i suoi webinar perché queste soluzioni di ottimizzazione non vengono proposte nei corsi dell’university di Mongo quindi senza i suoi insegnamenti io stesso sarei arrivato molto ma moooolto lentamente a trovare certe soluzioni, quindi grazie mille Massimo e visto che ci sono… e mettile le ultime 4 puntate del webinar che le stiamo tutti aspettando.