NoSQL-Datenbanken Kapitel 3: Document Stores Lars Kolb Sommersemester 2014 Universität Leipzig http://dbs.uni-leipzig.de 3-1 Inhaltsverzeichnis • Document Stores • CouchDB • MongoDB 3-2 Document Data Stores • Konzeptionell: Verschachtelte Tabelle mit erweiterbaren Attributen id 1 2 3 4 5 6 name fish.jpg trees.jpg snow.png hawaii.png hawaii.gif island.gif time 17:46 17:57 17:56 17:59 17:58 17:43 user camera bob john john john bob zztop nikon canon canon nikon canon nikon info width 100 30 64 128 320 640 tags height 200 250 64 64 128 480 size 12345 32091 1253 92834 49287 50398 [tuna, shark] [oak] [tahoe, powder] [maui, tuna] [maui] [maui] • Intern: Repräsentation als Dokumentenmenge (meist JSON-Format) {“_id”:”1”, "name":"fish.jpg",”time":”17:46","user":"bob“,"camera":"nikon", "info":{"width":100,"height":200,"size":12345},"tags":["tuna","shark"]} {“_id”:”2”, "name":"trees.jpg",“time":”17:57”,"user":"john”,"camera":"canon", "info":{"width":30,"height":250,"size":32091},"tags":["oak"]} .... Quelle: http://labs.mudynamics.com/wp-content/uploads/2009/04/icouch.html 3-3 Dokument-orientiert vs. relational Datenmodell Relational Dokument-orientiert Tabellen (festes Schema) Dokumente (beliebige Attribute) Beziehungen • Fremdschlüssel zwischen Entities • redundanzfrei • Eingebettet (Array, kompl. Attribut) • redundant bei 1:N, N:M Partitionierung schwierig auf verschiedene • Fremdschlüsselverweise auf Knoten gleichen Knoten Anfragen • einfache, standardisierte Formulierung (SQL) • flexibel und ausdrucksmächtig Performanz • performant pro Knoten (festes Schema erlaubt Optimierung) • Effizienzgewinn durch Parallelisierung begrenzt PS-Anbindung Impedence Mismatch (Datenkonvertierung nötig) 3-4 Inhaltsverzeichnis • Document Stores • CouchDB • MongoDB 3-5 CouchDB: Übersicht • Document Data Store – – – – verteilt, fehlertolerant Zugriff via RESTful HTTP-Requests (PUT=Insert, GET=Retrieve, ...) URL adressiert Server und Datenbank Request / Response enthalten JSON-Daten • Dokument – repräsentiert als JSON-Objekt – hat automatische generierte ID – hat fortlaufende Revisions-Nr, die bei Updates erhöht wird • Multi Version Concurrency Control (MVCC) – Handling mehrerer Versionen eines Dokuments • Master-Master-Architektur – unabhängige CouchDB-Datenbanken auf verschiedenen Servern (Knoten) – Synchronisation durch Merge-Replikation 3-6 CouchDB: Multi-Version Concurrency Control • Schreibzugriffe blockieren Lesezugriffe nicht – Client liest “zur Zeit aktuelle Version”, auch wenn parallel ein (noch nicht beendetes) Update läuft; nach Update liest Client neue Version – Eventual consistency • Vergleich RDBMS – Zugriff auf zu ändernde Datensätze wird verzögert (locking) – Erst nach abgeschlossenem Schreiben können Clients lesen – Strong consistency 3-7 Quelle für Bilder diese und nächste Folien: [CouchDB] CouchDB: Speicherung • Änderungsoperationen sind logische Einfügeoperationen – Hinzufügen eines neues Dokuments = neues Dokument mit neuer Id – Löschen eines Dokuments = neues Dokument mit alter Id und Flag “delete” – Ändern eines Dokuments = neues Dokument mit alter Id und neuer RevisionNr • Einfügen stets durch Anfügen von Daten in zwei Dateien – Index-File = Serialisierter B*-Baum zur effizienten Suche – Datenbank-File = Dokumente in Einfügereihenfolge – Kein Überschreiben von Daten geringerer Einfluss technischer Fehler (z.B. Stromausfall) auf bestehende Daten + effizient da weniger Disk-Seeks – Writes werden sequentialisiert pro Knoten • Konkurrierende Lesezugriffe (während Schreibzugriff) – Index-File ermöglicht stets den Zugriff auf die letzte konsistente Datenbankversion, selbst wenn Index-File gerade aktualisiert (d.h. erweitert) wird – Lese Index-File „von hinten“; beginne Suche ab erstem gefundenen Wurzelknoten (durch Flag speziell markiert) 3-8 CouchDB: Speicherung - Beispiel Beispiel: Dokumente 1, 2, 3, 5 und 7 werden in dieser Reihenfolge eingefügt B*-Baum Typ (1,1) • Zwischenknoten haben 2 oder 3 Söhne • Blattknoten haben bis zu 2 Einträge 3 2 1 Serialisierung in zwei Dateien • Index-File = Serialisierter B*-Baum 1 • DB-File = Dokumente in Einfügereihenfolge D1 2 D2 2 D3 3-9 3 D5 2 5, 7 D7 5 3 5 5, 7 3 CouchDB: Einfügen - Beispiel Beispiel: Neues Dokument (Id=6) wird eingefügt 3 2 1 2 5 3 3 2 5, 7 1 2 5 6 3 5 6,7 Update des Index- und DB-Files ausschliesslich durch Anfügen • Index-File: Pfad von geänderten Blattknoten zur Wurzel • DB-File: neues Dokument 1 2 2 D1 3 D2 5, 7 D3 5 D5 3 D7 3-10 5 D6 6,7 5 6 3 CouchDB: Update und Löschen - Beispiel • Ändert den B*-Baum nicht, nur Zeiger vom Blattknoten wird auf neue Dokumentenversion “umgebogen” 3 – Löschen = Update mit Flag “deleted” • Beispiel: Update Dokument 5 2 1 1 2 2 D1 D2 3 5, 7 D3 5 D5 3 D7 3-11 2 5, 7 D5’ 5 3 5 5, 7 3 CouchDB: Anfragen • Punkt oder Bereichsanfragen auf Dokumenten-Id – Ausnutzen des B*-Baums • Komplexe Anfragen (=Views) durch MapReduce (nächste Folien) 3-12 CouchDB-Anfragen mit MapReduce: Map • Erstellung eines B-Baums als Ergebnis der map-Funktion – Anwenden der map-Funktion auf alle Dokumente – Blatt-Knoten [Map-Output-Key, Map-Output-Value] – Innere Knoten mit Bereichen von Map-Output-Keys • Aktualisierung des B-Baums beim Einfügen / Löschen / Updates – Anwenden der map-Funktion auf neue/geänderte Dokumente – Reorganisation des B-Baums • Lazy-Ausführung, d.h. bei erstmaligem Query-Zeitpunkt – Spätere Queries arbeiten ausschließlich auf B-Baum, d.h. keine erneute map-Ausführung (falls Dokumente unverändert) 3-13 CouchDB-Anfragen mit MapReduce: Reduce • Voraggregation: Speicherung des Reduce-Ergebnisses pro Teilbaum – Flag: Rereduce = false – Beispiel: „Summe der Values“ – Key=„ch“ • reduce („ch“, [1], false) • reduce („ch“, [1,1,1], false) af:2,ch:1 ch:3 fr:1, it:2 sp:1, vi:2 • Anfrage-Ergebnis: Rekursive Bottom-up-Vereinigung der „Aggregate“ – ggf. Anwendung von Reduce-Funktion überlappenden Keys (Flag: Rereduce = true) – Key=„ch“: reduce („ch“, [1,3], true) • Vorteil – (Speicher-)Effiziente Wiederverwendung von vorberechneten Reduce-Ergebnissen – Map/Dokument-Änderung: Nur Aktualisierung des Pfads von Blatt zu Wurzel nötig – Effizienter Zugriff auf Anfrageergebnisse über Key(-Bereich) 3-14 CouchDB: Replikation und Konfliktauflösung • Replikation – Synchronisation des Datenbestandes zwischen Knoten – Manuell ausgelöst oder kontinuierlich – Interne Sequenz-Nummer wird genutzt um neue/geänderte Dokumente zu erkennen • Durchführung – Index- und DB-File werden “von hinten abgearbeitet” und entsprechende Änderungsoperationen an anderen Knoten geschickt – Konflikt bei parallelen Änderungen am gleichen Dokument • Konfliktauflösung – Identifizierung durch Flag “_conflict:true” – Jeder Knoten wählt eine Version als “winning version” durch deterministisches Verfahren (z.B. Nutzung der Revisions-Nummer) – keine “Abstimmung” zwischen Knoten – “loosing version” wird als normale ältere Version gespeichert – Anwendung kann/muss (bei Konflikt) mehrere Versionen lesen und ggf. “mischen” 3-15 Inhaltsverzeichnis • Document Stores • CouchDB • MongoDB 3-16 MongoDB • Verteilter Document Data Store – open source – JSON-Dokumente, gespeichert als BSON (Binary JSON) • Einfache Anfragesprache – Indexierung von Attributen möglich • Automatische Replikation mit Konsistenzwahrung • Skalierbarkeit durch Sharding 3-17 MongoDB: Anfragesprache • Teilmenge von SQL kann durch find-Funktion abgebildet werden, z.B. SQL MongoDB SELECT a,b FROM users WHERE age=33 db.users.find({age:33}, {a:1,b:1, _id:0}) SELECT * FROM users WHERE age>33 db.users.find({'age':{$gt:33}}) SELECT * FROM users WHERE name LIKE "%Joe%" db.users.find({name:/Joe/}) SELECT * FROM users ORDER BY name DESC db.users.find().sort({name:-1}) SELECT * FROM users LIMIT 10 SKIP 20 db.users.find().limit(10).skip(20) SELECT COUNT(AGE) from users db.users.find({age: {'$exists': true}}).count() [http://www.mongodb.org/display/DOCS/SQL+to+Mongo+Mapping+Chart] 3-18 MongoDB: Anfragesprache (2) { "_id":1, … "info":{"width":100, "height":200, "size":12345}, "tags":["tuna","shark"] } • Abfrage mehrwertiger Attribute: – Bilder mit dem tag "shark" : db.imgs.find({"tags": "shark"}) – Bilder mit den Tags "a", "b" und "c" : db.imgs.find({"tags": {$all:["a", "b", "c"]}}) – (Kein Fehler wenn das Attribut tags nicht vorhanden ist) • Abfrage geschachtelter Objekte: Bilder mit einer Breite kleiner 100px? – db.imgs.find({"info.width": {$lt:100}}) 3-19 3-20 ttp://rickosborne.org/blog/2010/02/infographicigrating-from-sql-to-mapreduce-with-mongodb/ MongoDB: SQL-Query mit MapReduce MongoDB: Aggregation Framework • Alternative zur Aggregationsberechnung mit MapReduce – Pipeline von Operatoren (http://docs.mongodb.org/manual/core/aggregation-pipeline) • • • • • $match: Selektion von Dokumenten $project: Hinzufügen/Unterdrücken/Umbenennen von Attributen, Attributwertberechnung $unwind: Unnesten geschachtelter Dokumente $group: Gruppierung und Aggregatbildung $sort, $limit, $skip Quelle: http://docs.mongodb.org/manual/reference/sql-aggregation-comparison/ 3-21 MongoDB: Index und Anfrageoptimierung • Für Anfragen ohne MapReduce können Indexes genutzt werden – – – – Aufbau und Verwendung analog zu RDBMS bis zu 64 Indexes bei mengenwertigen Attribute werden alle Elemente indexiert Indexierung von Attributen geschachtelter Dokumente ebenfalls möglich • Query-Optimierer – empirisch (Messen der Ausführungszeit von Query-Plänen ), nicht kostenbasiert – EXPLAIN-Operator analog zu RDBMS http://www.slideshare.net/mongodb/indexing-and-query-optimizer-mongo-austin 3-22 MongoDB: Replikation • Replica Sets = Asynchrone Master/Slave-Replikation – N Knoten wählen einen “primary” – Schreibzugriffe werden an “primary” gesendet und realisiert, anschließend Weiterleitung an (alle) anderen Knoten (“secondary”) – Lesezugriffe bei allen Knoten möglich • Schreib-Operation – Commit von Primary wenn Mehrheit der Knoten Daten geschrieben haben (asynchrone Replikation für noch ausstehende Knoten) – “Read uncommitted” möglich (wenn bei Primary comitted, aber noch nicht global) – Im Falle von Knotenausfall erfolgt Rollback (damit Aufgabe der Verfügbarkeit) • Knotenausfälle – Falls Primary ausfällt, dann wählen verbleibende Knoten neuen Primary – Neue / wiederkehrende Knoten werden durch Replikation aktualisiert http://www.slideshare.net/mongodb/replica-sets-nyc-nosql-meetup 3-23 MongoDB: Sharding • Horizontale Partitionierung (bzgl. eines Attributs) in Shards – jedes Shard ist selbst ein Replica Set (mehrere MongoDB-Knoten) • Range-Partitionierung – – – – Dokumente mit minKey <= K < maxKey in gleicher Partition (Chunk) Automatische Anpassung durch Range-Split wenn Chunk zu gross (200 MB) Günstige Wahl des Partitionierungs-Attributs entscheidend Routing durch speziellen MongoServer-Knoten MongoD MongoD MongoD MongoD MongoD MongoD MongoD MongoD MongoD MongoD MongoD MongoD MongoS MongoS Client Replica Set ... http://www.mongodb.org/display/DOCS/Sharding+Introduction 3-24 Vergleich CouchDB vs. MongoDB Eigenschaft Datenmodel Interface Anfragen CouchDB (AP) JSON HTTP/Rest • prozedural: MapReduce MongoDB (CP) JSON (BSON) Protokoll über TCP/IP • prozedural: MapReduce • deklarativ: Query Language Atomarität pro einzelnem Dokument pro einzelnem Dokument Skalierbarkeit durch Replikation durch Sharding Replikation Konkurrierende Zugriffe 3-25 http://www.slideshare.net/gabriele.lana/couchdb-vs-mongodb-2982288 Zusammenfassung • Cloud Data Stores – Fokus: flexible Datenstrukturen, Performanz – Realisierung durch Aufgabe der ACID-Eigenschaften und Datenkonsistenz • Arten – (einfache) Key-Value-Stores zur Verwaltung von Objekten – Document Stores zur Verwaltung semi-strukturierter Dokumente – Record Stores (siehe nächstes Kapitel) • Architektur bestimmt Eigenschaften des Systems (CAP-Theorem) – (meist) tolerant gegenüber Netzwerkpartitionierung – Aufgabe von Konsistenz durch Versionierung, eventual consistency und Konfliktlösung durch Nutzer – Aufgabe von Verfügbarkeit (Availability) durch hierarchische Architektur 3-26 Literatur • [CouchDB] J. Chris Anderson, Jan Lehnardt, Noah Slater: CouchDB: The Definitive Guide. O'Reilly Media, 2010 • [MongoDB] K. Chodorow, M. Dirolf: MongoDB: The Definitive Guide. O'Reilly Media, 2010 3-27