Skip to content
Snippets Groups Projects
Commit ff9b6e0d authored by Stefan Keller's avatar Stefan Keller Committed by Marcel Huber
Browse files

Update README.md

parent a4560954
Branches
Tags
No related merge requests found
# Übung 13: Key-Value Store
# Dbs2 - Übung 13 (Entwurf)
## Lernziele
Siehe https://gitlab.dev.ifs.hsr.ch/m1huber/Dbs2Uebungen/blob/patch-1/KeyValueStore/README.md
- ??
# Übung 13: NoSQL ff. sowie Prüfungsvorbereitung
## Vorbereitung
Dies ist eine spezielle Übung, denn die Vorlesung dieser Woche fällt aus. Die Übung zu Key-Value Store entfällt. Dabei ist darauf hinzuwesien, dass das Thema Key-Value Stores einerseits in der Vorlesung behandelt wurde, sowie andererseits in den Übungen zu Dictionnaries (hstore!) mit PostgreSQL.
tbd.
Diese Übung besteht aus folgenden, unterschiedlichen Teilen:
1. MonetDB ff. - Charakterisierung und Prüfungsfragen
2. MongoDB ff - Sharding, Queries und Prüfungsfragen
3. Neo4J - Prüfungsfragen
***Hinweise:***
Diese Übung ist eine reine Diskussion-, Denk- und Papier-Übung mit zusätzlichen Informationen zu den NoSQL Stores MonetDB, MongoDB und Neo4J.
Da die Vorlesung Informationssysteme im FS 2018 teilweise neuen Stoff behandelt gegenüber früher, haben wir in dieser Übungsstunde als Dienstleistung extra für Sie mögliche Prüfungsfragen zu einigen der neuen NoSQL-Themen zusammengestellt.
Auf dem Skripteserver gibt es ein Verzeichnis "/Pruefungen alte/" mit alten Prüfungen aus den Vorjahren. Darunter ist auch eine Prüfung mit Lösungen. Ansonsten werden Lösungen weder abgegeben noch diskutiert - ausser hier.
## Aufgaben 1: MonetDB ff. - Charakterisierung und Prüfungsfragen
### Lernziele
- Charakteristika von Column Stores kennenlernen
- Definition In-Memory und MonetDB
### Aufgabe 1.1: Vergleich MonetDB mit PostgreSQL
Als Vorbereitung wird voraussgesetzt, dass Sie die Übung 12 "In-Memory Column Store MonetDB" durchgearbeitet haben sowie Zugang zu MonetDB mit geladener Datenbank Ds2 (DVD Store) haben.
Lesen Sie zudem mind. diesen beiden MonetDB-Doku.-Unterkatpiel durch: https://www.monetdb.org/Documentation/Manuals/MonetDB/Architecture und https://www.monetdb.org/Documentation/Manuals/MonetDB/Architecture/Storagemodel und https://www.monetdb.org/blog/monetdb-sql-transaction-management-scheme .
Vergleichen Sie die Queries von MongoDB mit derselben in PostgreSQL, welche dieselbe DVD-Datenbank geladen "ds2" hat.
Obschon Benchmarking schwierig ist, lassen sich folgende allgemeine Aussagen machen:
- MonetDB ist schnell (schneller als z.B. PostgreSQL), wenn es um Aggregationsfunktionen geht (GROUP BY, SUM/AVG) und wenn nur wenige Ausgabe-Felder (Columns, Attributes) benötigt werden.
- PostgreSQL ist typischerweise bei der ersten Query-Durchführung (= Kaltstart) oft langsamer und dann bei der wiederholten Query-Durchführung schneller.
- Diese Unterschiede von Kalt- zu Warmstart sind bei MonetDB geringer; dies besonders wenn die Daten im Memory Platz haben.
### Aufgabe 1.2: Diskussion In-Memory Stores
MonetDB ist keine echte In-Memory Datenbank. MonetDB verwendet "Memory-Mapped File Arrays" (). Wenn MonetDB eine memory-mapped Datei verwendet, kann sie die Daten direkt im Speicher auf der Festplatte abbilden (Array). Bei einer SQL-Query, wird sie auf eine mmap-Datei abgebildet und dann vom Kernel des Betriebssystems in den Speicher geladen. Wenn die Datensätze nicht mehr verwendet werden, wird ihr Speicherplatz freigeben (virtuelle Speicherverwaltung).
Memory/RAM-Zugriffe sind schneller als Disk-Zugriffe. In-Memory-Datenbanken halten den gesamten Datensatz im Memory und beantworten alle Anfragen daraus. Der Nachteil ist, dass die maximale Grösse der Daten durch das verfügbare RAM begrenzt sind. Redis z.B. hat verschiedene Möglichkeiten, die Daten dauerhaft auf Disk zu speichern. Die Disk-Repräsentation kann dann verwendet werden, um den In-Memory-Zustand einer Redis-Instanz wiederherzustellen. Diese Repräsentation ist bei Redis jedoch nicht indiziert und kann nicht verwendet werden, um Anfragen direkt von der Festplatte zu beantworten.
Dies steht im Gegensatz zu RDBMS-Datenbanken wie PostgreSQL: RDBMS halten immer den gesamten Datensatz einschliesslich der Indizes auf der Festplatte in einem Format, das einen Random-Zugriff erlaubt. Queries können direkt aus den Daten auf der Festplatte beantwortet werden. Die Datenbank kann als Optimierung Caches oder Indizes in den Speicher laden, aber das ist nicht unbedingt notwendig. Eine RDBMS kann mehr Daten verarbeiten, als in den Arbeitsspeicher passen.
Ein wichtiger Unterschied zwischen In-Memory- und RDBMS besteht darin, wie sie mit Schreibvorgängen umgehen, d.h. welche Persistenzgarantien sie bieten. Es gibt hier viele verschiedene Implementationen von denen Logging und Snapshots die wichtigsten sind.
*Snapshots*: Hier speichern In-Memory Stores die Daten in regelmässigen Abständen dauerhaft, während RDBMS in der Regel vor jeder Transaktion als abgeschlossen markieren. Dies bedeutet, dass RDBMS potentiell langsamer sind, weil sie häufiger committen, während In-Memory Stores normalerweise ein Zeitfenster haben, in dem Datenverlust auftreten kann, selbst wenn dem Client mitgeteilt wurde, dass sein Update erfolgreich war. Dieser Datenverlust kann in einem bestimmten Anwendungsfall ein akzeptabler Kompromiss sein.
*Logging*: Siehe diesen Blog Post: https://medium.com/@denisanikin/what-an-in-memory-database-is-and-how-it-persists-data-efficiently-f43868cff4c1 .
### Aufgabe 1.3: Mögliche Prüfungsfragen
Frage: Was ist eine In-Memory DB und wie passt MonetDB dazu?
Frage: Diskutieren Sie die Vorteile von Column-Store gegebenüber Row-Stores in mind. drei Sätzen?
## Aufgaben 2: MongoDB ff. - Sharding, Queries und Prüfungsfragen
### Lernziele
- Kennenlernen, wie MongoDB Sharding implementiert und auf was geachtet werden muss
- Kennenlernen wie was es für Beziehungs-Funktionen in MongoDB gibt (v.a. für 1:M-Beziehungen)
### Vorbereitung
Als erste Vorbereitung wird vorausgesetzt, dass Ihnen die Übung 10 "MongoDB Intro." bekannt ist.
Schauen Sie bei der Bearbeitung der untenstehenden Aufgaben jeweils diese Dokumentation zu Sharding mit MongoDB an: https://docs.mongodb.com/manual/sharding/ .
### Aufgabe 2.1: Sharding
Lesen Sie zuerst folgenden Blog-Post "Sharding data collections with MongoDB" durch: http://vargas-solar.com/big-data-analytics/hands-on/sharding/ . Beachten Sie dabei vorher folgende Themen bzw. beantworten Sie danach folgende Fragen:
1. Was ist Sharding?
1. Welche Strategien (Arten) von Sharding kennt MongoDB?
1. Was ist ein Shard Key?
1. Was sind die Vorteil des Sharding?
1. Was ist bei der Wahl eines Ranged Shard Keys zu beachten?
Stichworte zu den Antworten:
1. Sharding ist horizontale Partitionierung auf Nodes die eigenständige Prozesse, Memory und Disks haben ("Horizontal Scaling Out" mit "Shared nothing"-Architektur). Vgl. dazu die Vorlesung. Gemäss MongoDB ist es "Sharding is a mechanism for scaling writes by distributing them across multiple shards".
1. MongoDB kennt die beiden Sharding-Stratgien "Range-based" und "Hash-based (horizontal) Partitioning".
1. "Shard Key": Ein Shard Key besteht aus einem oder mehreren unveränderlichen (immutable) Feldern, die in jedem Dokument einer Collection vorhanden sein müssen. Um die Dokumente in einer Collection zu verteilen ("sharden"), partitioniert MongoDB die Collection mit dem Shard Key ("Splitterschlüssel"). Der Datenbank-Administrator wählt den Shard Key beim Erstellen einer Collection. Die Shard Key-Konfiguration kann danach nicht mehr verändert werden.
1. Die Vorteile des Sharding sind hier beschrieben: https://docs.mongodb.com/manual/sharding/ .
Bei (5), der Wahl eines Ranged Shard Keys, ist folgendes zu beachten:
Die Kardinalität eines Shard Key bestimmt die maximale Anzahl von Partitionen, die der Balancer erzeugen kann. Ein guter Shard Key ist einer mit hoher Kardinalität (Cardinality) und niedriger Häufigkeit (Frequency). Dies erleichtert aber die horizontale Skalierung bzw. gleichmässige Verteilung der Daten. Man berücksichtige jeden dieser Faktoren bei der Auswahl eines Splitterschlüssels. Wenn ein Datenmodell ein Sharding auf einen Schlüssel mit niedriger Kardinalität erfordert, kann man auch einen zusammengesetzten Index mit einem Feld mit höherer Kardinalität verwenden.
Die Häufigkeit des Splitterschlüssels gibt an, wie oft ein bestimmter Wert in den Daten vorkommt. Gute Kandidaten sind Felder mit kleiner Häufgkeit. Ein monoton aufsteigender Schlüsselwert - wie namentlich der Idenfitikator (id) - ist zu vermeiden, denn damit würde nur der erste Shard/Partition verwendet, was die Verteilung verunmöglicht oder aber ggf. zu aufwändigen Datenbank-internen Reorganisationen führt (vgl. https://docs.mongodb.com/manual/core/sharding-shard-key/#choosing-a-shard-key).
Zum Vergleich: Beim Hash-based Sharding genügt es, das Feld der Collection anzugeben (z.B. Identifikator), der Hash wird dann vom System berechnet. Man beachte auch die Ähnlichkeit eines hash-based Shard Keysvon MongoDB mit dem Partition Key von Amazons DynamoDB: https://aws.amazon.com/de/blogs/database/choosing-the-right-dynamodb-partition-key/ (Quelle: AWS Database Blog zu "Choosing the Right DynamoDB Partition Key").
### Aufgabe 2.2: Queries ff.
Gegeben seien folgende Daten aus der MongoDB-Übung 2.3:
`
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d730"), name:
'Leto'})
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d731"), name:
'Duncan',
manager: ObjectId("4d85c7039ab0fd70a117d730")});
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d732"), name:
'Moneo',
manager: ObjectId("4d85c7039ab0fd70a117d730")});
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d733"), name:
'Siona',
manager: [ObjectId("4d85c7039ab0fd70a117d730"),
ObjectId("4d85c7039ab0fd70a117d732")] })
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d734"), name:
'Ghanima',
family: {mother: 'Chani', father: 'Paul',
brother: ObjectId("4d85c7039ab0fd70a117d730")}})
`
Finde alle Angestellte zum Manager mit Namen 'Leto'.
Query:
`db.employees.find({manager:{$in:[db.employees.findOne({name:'Leto'},{_id:1})._id]}},{_id:0})`
Ausgabe:
`{ "name" : "Duncan", "manager" : ObjectId("4d85c7039ab0fd70a117d730") }
{ "name" : "Moneo", "manager" : ObjectId("4d85c7039ab0fd70a117d730") }
{ "name" : "Siona", "manager" : [ ObjectId("4d85c7039ab0fd70a117d730"),
ObjectId("4d85c7039ab0fd70a117d732") ] }
`
### Aufgabe 2.3: Mögliche Prüfungsfrage zu Transaktionen
Frage: MongoDB und Transaktionsscherheit: Kreuzen Sie die richtige(n) Aussagen an (Multiple Choice, mehrere Antworten, Abzüge bei falschen Angaben):
1. Transaktion pro Operation auf ein Dokument
1. Transaktion pro Query
1. Transaktion über mehrere Operationen und Dokumente hinweg
1. ...
*Antwort: 1 ist richtig: MongoDB erlaubt aktuell Transaktionssicherheit nur auf dem aktuellem Document.
=> Erfinden Sie weitere mögliche richtige und falsche Antworten!
### Aufgabe 2.4: Mögliche Prüfungsfragen zu Queries
*Hinweis* Die Abfrage von Beziehungen zwischen unabhängigen Dokumenten - also das was mit RDBMS-Joins selbstverständlich ist - wurden nicht behandet (Interessierte suchen nach "Joins in MongoDB" mit $lookup).
2.4.1: Gegeben folgende Daten (???), notieren Sie die Ausgabe und beschreiben Sie die Query in knappen Worten.
(???) find mit filter, bspw. .., loves: { $all/$in:[...]}
`db.inventory.find( { qty: { $exists: true, $in: [ 5, 15 ] } } )`
*=> Antwort: This query will select all documents in the inventory collection where the qty field exists and its value is equal to 5 or 15.*
2.4.2: Update Falle: Bei Update muss man $set/$push/$inc brauchen, um Änderungen an einem bestehenden Dokument inkrementell durchzuführen.
Frage: In einem Update soll die quantity aller products mit benannter sku und quantity > 0 um 1 dekrementiert werden. Zusätzlich soll vermerkt werden, wer das gerade am Machen ist:
`db.products.update ( { sku: "SomeSkuID", quantity: { $gt: 0 } }, { $inc:
{ quantity: -1 }, $push: { checkout: { by: "OtherUserID", date: new
Date() } } } )`
2.4.3 Was wird bei dieser Query ausgegeben? _id, name, price, size
`db.products.find({"name":"Tshirt"} , {name:1, price:1, size:1})`
2.4.4. Was fehlt um _id zu unterdrücken? _id:0
`db.products.find({"name":"Tshirt"} , {name:1, price:1, size:1, _id:0})`
2.4.5: Was bewirkt `elemeMatch` in folgender Query?
`db.scores.find({ results: { $elemMatch: { $gte: 80, $lt: 85 } } }) { "_id" : 1, "results" : [ 82, 85, 88 ] }`
Hinweis: $elemeMatch: Siehe MongoDB-Doku.
<!-- SOLUTION!
- ***Lösungsvorschlag***
``` sql
DROP TABLE IF EXISTS TBD;
```
SOLUTION -->
## Aufgaben 3: Neo4J - Prüfungsfragen
### Vorbereitung
**Hinweise:**
- Siehe Übung 11: Graph Stores.
- tbd.
## Aufgaben
### 3.1 Mögliche Prüfungsfrage zu einer Cipher-Query
### Aufgabe 1: tbd.
Gegeben folgende Daten mit Graph ein Query
- Notieren Sie die exakte Ausgabe auf einem Terminal.
- Kommentieren Sie, was die Query tut.
Daten einfügen:
`CREATE (alice:Reader {name:'Alice'}), (bob:Reader {name:'Bob'}), (william:Author {name:'William'}), (dune:Book {title:'Dune'}), (hamlet:Book {title:'Hamlet'}), (othello:Book {title:'Othello'}), (alice)-[:LIKES]->(dune), (bob)-[:LIKES]->(dune), (bob)-[:LIKES]->(hamlet), (bob)-[:LIKES]->(othello), (william)-[:WROTE]->(hamlet),
(william)-[:WROTE]->(othello)`
![Abbildung](https://md.coredump.ch/uploads/upload_e1080299d9f4865cda67f764569b2eb6.png)
*Abbildung: Neo4J Beispiel-Graph.*
Query:
`MATCH (:Reader {name:'Alice'})-[:LIKES]->(:Book {title:'Dune'})
<-[:LIKES]-(:Reader)-[:LIKES]->(books:Book)
RETURN books.title`
tbd.
<!-- SOLUTION
- ***Lösungsvorschlag***
tbd.
``` sql
DROP TABLE IF EXISTS TBD;
╒═════════════╕
│"books.title"│
╞═════════════╡
│"Othello" │
├─────────────┤
│"Hamlet" │
└─────────────┘
```
SOLUTION -->
## Musterlösung
## Musterlösung zu den Aufgaben 1 - 3
Die Musterlösung zu dieser Übung finden Sie auf [dieser
Seite](KeyValueStore/README.solutions.md) oder als
......@@ -35,12 +258,12 @@ Datei.
---
keywords:
- database
- distributed
- replication
- sharding
- cluster
- mongodb
- nosql
title: 'Übung 13: Key-Value Store'
- sharding
- relationships
- graphdb
- exam
title: 'Übung 13: NoSQL ff.'
---
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment