Pirma parte del seminario su NoSQL al DiTeDi di Udine del 15/12/2012. Affrontato il caso di studio di un'architettura enterprise, basata su datastore relazionali (PostgreSQL) e non (CouchDB, MongoDB, Redis e OrientDB).
25. PostgreSQL
25
SELECT titolo, max(visioni) FROM film;
SELECT titolo, max(visioni) FROM film;
SQL error:
ERROR: column "film.titolo" must appear in the GROUP BY clause or
be used in an aggregate function at character 8
In statement:
SELECT titolo, max(visioni) FROM film;
26. PostgreSQL
26
SELECT titolo, max(visioni) FROM film;
SELECT titolo, max(visioni) FROM film;
SQL error:
ERROR: column "film.titolo" must appear in the GROUP BY clause or
be used in an aggregate function at character 8
In statement:
SELECT titolo, max(visioni) FROM film;
27. 27
Disclaimer: Ciò non significa che non utilizziamo anche MySQL in determinati contesti
Ocio però!
30. Possibile Soluzione
30
CREATE VIEW film AS
SELECT titolo, anno, visioni FROM film_provider1
UNION
SELECT titolo, anno, visioni FROM film_provider2;
35. Write Ahead Log (Journal)
• Apri il Log
• Scrivici informazioni tipo “Questo dato va
qui (offset)”
• Scrivi il file
• Tenta il salvataggio su disco (fsync)
• Modifica i dati
• Segna sul Log che le operazioni sono
state compiute
35
http://www.depesz.com/2011/07/14/write-ahead-log-understanding-postgresql-conf-checkpoint_segments-checkpoint_timeout-checkpoint_warning/
50. Non potete avere tutto, ragazzi!
Prof. Eric Brewer
http://www.cs.berkeley.edu/~brewer/
51. Se volete distribuire una base
dati, qualora si venga a creare
un partizionamento, dovete
scegliere tra coerenza dei dati
e disponibilità del servizio.
CAP Theorem, Nancy Lynch and Seth Gilbert, “Brewer's conjecture and the feasibility
of consistent, available, partition-tolerant web services”, ACM SIGACT News, Volume
33 Issue 2 (2002), pg. 51-59.
64. Cos’è CouchDB?
• Datastore Documentale (JSON)
• Interfaccia HTTP
• Replicazione master-master (con filtri)
• Può contenere applicazioni Web
HTML/CSS/JS (Couchapp)
• Pensato per contesti distribuiti
• Un progetto dalla storia “travagliata”
64
72. Versioni
• ID / _rev
• Meglio generare da se gli ID (sequenziali)
• Aggiornamenti atomici sui documenti
• Aggiornamento ottimista, MVCC
• Coerenza Eventuale
72
93. Indicatori di Performance
• 350 evt/sec in inserimento
• 3000 evt/sec se in batch mode
• 100 evt/sec su update
• 10 evt/sec durante compattazione
93
• NB: dati forniti unicamente per dare ordini di grandezza. Test eseguiti su server entry level IBM x3550
M3, 1x3.60 GHz Xeon, 4GB RAM, Dischi SAS in RAID 0
• CouchDB configurato con httpd max_connections = 2048, export ERL_MAX_PORTS=4096, export
ERL_FLAGS="+A 4«, fsync
99. Da considerare:
• Inerentemente più rischioso
• Più onerosa la manutenzione e il backup
degli shard
• Delicato decidere con quali criteri
• In SQL: “Join” tra shards costosi.
Replicazione delle tabelle “globali” – es.
categorie film
99
101. Recap su CouchDB:
• Ottima soluzione per contesti distribuiti
• Non adatto per situazioni con frequenti
aggiornamenti e carichi (ingenti) costanti
• API REST aiuta a scalare le letture
• Bigcouch in aiuto sulle scritture
• Architetture innovative con le Couchapp
• Si possono usare strumenti Tipici Web:
HAproxy, Nginx
101
102. Da Tenere a Mente:
• Attenzione alla generazione degli ID,
specie se distribuiti
• Lo spazio su disco cresce e la
compattazione «inchioda» lo strumento
• I «driver» disponibili non sempre sono di
alta qualità...
102
103. Da Tenere sotto controllo:
• TouchDB
database CouchDB compatibile,
adatto all’embedding in device
mobili
• PouchDB
libreria js: come avere
CouchDB nel browser
103
108. Cosa ci serve?
• Flessibilità del modello dati
• Semplicità
• Facilità di dialogo con PHP
• Scalabilità sulle letture
• Flessibilità di query
108
109. Perché no CouchDB?
• Flessibilità del modello dati
• Semplicità
• Facilità di dialogo con PHP
• Scalabilità sulle letture
• Flessibilità di query
109
120. In CouchDB
120
function(doc) {
if (doc.info_type == 'view') {
emit(doc.movie, doc.views);
}
}
Map:
{
"_id": "39c7c57...",
"info_type": "view",
"movie": "The Gladiator",
"views": 37
}
121. Cosa fa il map?
121
Map:
function(doc) {
if (doc.info_type == 'view') {
emit(doc.movie, doc.views);
}
}
{
"movie": "Spiderman",
"views": 10
}
{
"movie": "The Gladiator",
"views": 37
}
{
"movie": "Shrek",
"views": 25
}
10 37 25
122. Cosa fa il reduce?
122
Reduce:
function (key, values, rereduce) {
return sum(values);
}
10 37 25
47 25
123. Dov’è il problema?
123
function(doc) {
if (doc.info_type == 'config') {
for (param in doc.params) {
emit(param, doc.params[param]);
}
}
}
Map:
Reduce:
.... Non possiamo avere parametri in input!
Viste precalcolate su
ciascun documento
133. Recap su MongoDB:
• Semplice (arma a doppio taglio!)
• Linguaggio d’interrogazione potente
• Ottima documentazione
• Flessibilità nella configurazione
• Driver disponibili per molti linguaggi
• Sviluppo molto attivo
• Supporto
133
134. Fare attenzione a:
• Opzione safe, journaling
• Si inchioda negli ordinamenti se non
definiti indici
• Attenzione ai nomi!
• Non farsi coinvolgere e cercare di
costruirci sopra DB relazionali
134
137. Cosa abbiamo considerato?
• Performance
• Semplicità
• Expiration automatico dei valori
• Gestione del cold start
• Non è un problema la perdita di dati
-> Ok persistenza volatile, no replicazione
137
138. Perchè no Couch/Mongo?
• Couch occupa troppo spazio, troppo lento
• MongoDB poteva starci (soprattutto
perché TTL introdotte da poco – 12/09);
• Ma ci sono soluzioni più semplici…
138
140. About Redis
• Key/Value++
• Progetto Italiano (Salvatore Sanfilippo)
• Protocollo Binario
• Sponsorizzato da VMWare
• Gestione expiry delle chiavi
140
141. Esempi di query
141
// Memorizzare un valore
> SET status ok
// Collezioni
> SADD luci_accese camera bagno
// Valore con scadenza prefissata
> SET status ok
> EXPIRE status 10 // in secondi
143. Recap su Redis:
• E’ molto veloce
• Salva su RAM (snapshot su disco)
• E’ un’ottima soluzione di caching,
evitando problema cold start
• Necessario avere abbastanza RAM
• Può essere usato per delegare alcuni
calcoli costosi
143
155. Con strumenti visti prima…
• Query di Couch poco flessibili
• Redis assenza indici secondari
• MongoDB e Postgres forse ok ma limiti
nel traversare nodi non immediatamente
adiacenti
155
157. Con RDBMS
157
SELECT p1 . * , p2 . * , v . *
FROM pagina AS p1
JOIN visita AS v ON v.pagina_da = p1.id
JOIN pagina AS p2 ON v.pagina_a = p2.id
WHERE p1.id =1
AND v.data_visita >0
AND v.data_visita <4
158. Il problema…
158
SELECT p1 . * , p2 . * , v . *
FROM pagina AS p1
JOIN visita AS v ON v.pagina_da = p1.id
JOIN pagina AS p2 ON v.pagina_a = p2.id
WHERE p1.id =1
AND v.data_visita >0
AND v.data_visita <4
O(log N) O(log M) O(log N)
159. Invece con un grafo:
159
O(1)
O(1)
Adiacenza senza necessità di consultare un indice!
166. Recap su OrientDB:
• Ottima soluzione per gestire relazioni
• Traversa 5 Milioni+ di record/sec
• Progetto Italiano (Luca Garulli)
• ACID
• Supporta ereditarietà
• Semplice da installare e avviare
166
168. Ringraziamento
168
Il know how utilizzato per la preparazione di questa presentazione è
stato in buona parte acquisito durante lo sviluppo del sistema Hotel
OnAir di concezione e proprietà di VDA Multimedia Spa, cui il case
study di cui si è fatto accenno fa riferimento.
Ringraziamo il team leader del progetto, Stefano Brenelli, e tutto il team
di sviluppo, per l'interessante, edificante e proficua collaborazione. In
particolare ringraziamo: Carlo Anselmi, Maurizio Battistella, Manuel
Bitto, Nicola Busanello, Antonino Murador, Antonio Parrella, Nicola
Pressi, Riccardo Zamuner, Michele Zanon, Tiziano Zonta.
Ringraziamo anche i colleghi Diego Drigani e Dario Tion, nonchè tutto il
PUG Friuli per i sempre utili confronti e consigli.