MongoDB kompakt - Johannes Schildgen - E-Book

MongoDB kompakt E-Book

Johannes Schildgen

0,0

Beschreibung

Die Dokumentendatenbank MongoDB ist das am weitesten verbreitete NoSQL-Datenbanksystem. Dieses kompakte Werk präsentiert MongoDB von der Installation bis zur Administrierung in großen Rechenclustern. Sie erfahren, wie Sie JSON-Dokumente in Kollektionen einfügen, suchen, ändern und löschen, wie man Replikation und Sharding effektiv einsetzt und wie Sie komplexe Analysen mithilfe der Aggregation-Pipeline durchführen können.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern
Kindle™-E-Readern
(für ausgewählte Pakete)

Seitenzahl: 125

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Inhaltsverzeichnis

NoSQL-Datenbanken

1.1 Willkommen in der NoSQL-Welt

1.2 Klassifizierung

1.2.1 Key-Value-Datenbanken

1.2.2 Wide-Column-Stores

1.2.3 Dokumentendatenbanken

1.2.4 Graphdatenbanken

1.3 Verteilte Datenbanken

MongoDB

2.1 Installation und Betrieb

2.1.1 Installation von MongoDB

2.1.2 mongod: Starten des Servers

2.1.3 Die MongoDB Shell

2.1.4 Authentication

2.1.5 JSON-Dokumente

2.1.6 NumberDecimal

2.1.7 BSON: Binary JSON

2.1.8 Import und Export von Dokumenten

2.1.9 MongoDB Compass

2.2 Datenbankanfragen

2.2.1 Collections

2.2.2 Einfügen von Dokumenten

2.2.3 Dokumente finden

2.2.4 Sortieren und Limitieren

2.2.5 Projektion

2.2.6 Selektion

2.2.7 Dokumente zählen

2.2.8 Änderungsoperationen

2.2.9 Dokumente löschen

2.3 Komplexe Datentypen

2.3.1 Subdokumente / Dot-Notation

2.3.2 Arrays

2.4 Capped Collections

2.5 Datenmodellierung

2.6 GridFS

2.7 JavaScript

Performance

3.1 Monitoring

3.2 Profiling

3.3 Anfragepläne

3.3.1 Explain-Pläne

3.3.2 Ausführungsstatistiken

3.3.3 COLLSCAN: Collection-Scan

3.4 Indexe

3.4.1 IXSCAN: Index Scan

3.4.2 Index bei der Präfix-Suche

3.4.3 Collations

3.4.4 Text-Indexe

3.4.5 Mehrdimensionale Indexe

3.4.6 Index über Subdokumente

3.4.7 MultiKey-Indexe über Arrays

3.4.8 Geodaten und Geo-Indexe

3.4.9 Weitere Index-Optionen

3.5 Storage Engines

Replikation

4.1 Replikation starten

4.2 Write Concern

4.3 secondaryOk

4.4 Lesepräferenz

4.5 Statement-basierte Replikation

4.6 Arbiter

Sharding

5.1 Bereichs- / Hash-Partitionierung

5.2 Sharding und Replikation

5.3 Config-Server

5.4 mongos: Sharding-Server

5.5 Eine Collection „sharden“

5.6 Sharding-Status

5.7 Gute Shard-Keys - Schlechte Shard-Keys

Aggregation Pipeline

6.1 Pipeline-Schritte

6.1.1 $match: Selektion

6.1.2 $sort: Sortieren

6.1.3 $limit und $skip

6.1.4 $project: Projektion

6.1.5 $group: Gruppieren und Aggregieren

6.1.6 $unwind: Arrays aufsplitten

6.1.7 $lookup: Verbundoperationen

6.1.8 $out: Ausgabe in Collection schreiben

6.1.9 Weitere Schritte und Optionen

6.2 Verteilte Berechnung

Übungen

7.1 Übungsaufgaben

7.1.1 CRUD-Operationen

7.1.2 Anfragepläne, Indexe

7.1.3 Replikation

7.1.4 Aggregation Pipeline

7.2 Lösungen

7.2.1 CRUD-Operationen

7.2.2 Anfragepläne, Indexe

7.2.3 Replikation

7.2.4 Aggregation Pipeline

Index

1. NoSQL-Datenbanken

1.1 Willkommen in der NoSQL-Welt

Der Begriff NoSQL darf nicht als Aufschrei „Kein SQL!“ missverstanden werden, sondern er ist vielmehr die Abkürzung für „Not only SQL“. Obwohl sich die Structured Query Language (SQL) und relationale Datenbanksysteme in den meisten Bereichen durchgesetzt haben und obwohl in diesen Systemen jahrzehntelange Forschungen und Weiterentwicklungen gemacht wurden, ist es an der Zeit zu realisieren, dass es nicht nur SQL, sondern auch nützliche Alternativen gibt.

Relationale Datenbanken und die Anfragesprache SQL setzen ein festes Tabellenschema voraus. Man nennt die in relationalen Datenbanken gespeicherten Daten auch strukturierte Daten. Die Unterstützung von unbekannten und heterogenen Datenstrukturen, flexiblen Schemata sowie semistrukturierten oder unstrukturierten Daten in SQL ist sehr beschränkt. Das erkennt man bereits daran, dass mit der SQL Data Definition Language (DDL) zuerst Tabellen erstellt und dabei alle ihre Spalten und Datentypen angeben werden müssen, bevor man Daten einfügen und suchen kann. Nachträgliche Änderungen am Schema sind zwar möglich, aber sollten vor allem bei mit vielen Datensätzen gefüllten Tabellen besser nicht ständig erfolgen. NoSQL-Datenbanken bieten hier den Vorteil der Schema-Flexibilität. Es muss nicht von vornherein festgelegt werden, welche Attribute die Datensätze haben werden und von welchen Datentypen diese sind. Es ist sogar erlaubt, dass alle Datensätze eine unterschiedliche Struktur haben. In relationalen Datenbanken wäre das undenkbar. Dort herrscht horizontale Homogenität, welche besagt, dass in einer Tabelle alle Zeilen die gleichen Spalten haben müssen - Nullwerte sind zwar erlaubt, aber sie belegen trotzdem Platz -, sowie vertikale Homogenität, die dafür steht, dass innerhalb einer Tabellenspalte alle Zeilen den gleichen Datentyp haben müssen.

NoSQL-Datenbanken adressieren die Probleme der Speicherung und Verarbeitung von Big Data. Gerne charakterisiert man Big Data mit (mindestens) drei Vs. Das erste steht für Volume, also enorm große Datenmengen, das zweite für Velocity, was für die hohe Geschwindigkeit steht, mit der neue Daten geschrieben werden. Das dritte V haben wir bereits im vorherigen Absatz diskutiert, die Variety, also die Heterogenität der Daten.

Neuartige Anwendungen aus den Bereichen Web, Data Mining und Wissenschaft haben andere Anforderungen als klassische Anwendungen, für die relationale Datenbanksysteme weiterhin optimal sind. Im Web wird beispielsweise das ACID-Paradigma nicht immer so genau genommen. ACID steht für Atomarität, Konsistenz, Isolation und Dauerhaftigkeit und ist beispielsweise in Bankanwendungen unbedingt notwendig, damit Transaktionen korrekt ausgeführt werden und damit parallel laufende Anwendungen sich nicht gegenseitig beeinflussen. Viele relationale Datenbanksysteme laufen auf einem einzigen Rechner. Um mit den großen Datenmengen, die beispielsweise in sozialen Netzwerken und Online Shops anfallen, adäquat arbeiten zu können, setzt man auf verteilte Datenbanksysteme, also solche, die auf mehreren Rechnern laufen und somit sowohl die Speicherung als auch die Berechnung der Daten verteilen. In solch verteilten Systemen lässt es sich nicht vermeiden, dass ein Datenaustausch zwischen Rechnern mal verzögert ausgeführt wird, dass Nachrichten verloren gehen oder Teile des Netzwerks kurzzeitig unerreichbar sind. Man nennt diesen Zustand eine Netzwerkpartition. Ein verteiltes Datenbanksystem muss solche Netzwerkpartitionen tolerieren. Das berühmte CAP-Theorem (CAP steht für Consistency, Availability und Partition Tolerance) besagt, dass man von den drei Eigenschaften Konsistenz, Verfügbarkeit und Partitionstoleranz nur zwei auf einmal erreichen kann. Da wir, wie gerade beschrieben, in verteilten Systemen zwingend Partitionstoleranz erfordern, muss man sich also entweder für Verfügbarkeit oder Konsistenz entscheiden. Stellen wir uns eine Reisebuchungswebseite vor, auf der der Preis einer bestimmten Reise um zwanzig Euro erhöht werden soll. In einer verteilten Datenbank wird nun diese Änderung auf mehreren Rechnern im Netzwerk ausgeführt. Ist dem Betreiber der Webseite die starke Konsistenz so wichtig, dass er es nicht toleriert, dass innerhalb der nächsten Sekunden oder Minuten ein Besucher noch den alten Preis der Reise sieht, muss er bei Netzwerkproblemen damit bezahlen, dass seine Webseite für einige Zeit unerreichbar ist. Denn erst, wenn sich die Rechner wieder synchronisiert haben und der neue Preis auf allen Rechnern angekommen ist, darf der Datensatz wieder gelesen werden. Entscheidet sich der Reisewebsitebetreiber stattdessen für die Verfügbarkeit, kann es beispielsweise bei Nachrichtenverzögerungen im Netzwerk kurzzeitig passieren, dass eine Besucherin einen veralteten Wert, also den niedrigen Preis, sieht. Diese Konsistenzstufe wird Eventual Consistency genannt, was mit „schließlich konsistent“ zu übersetzen ist. Schließlich, also irgendwann in naher Zukunft, wird die Änderung alle Rechner erreicht haben. Zwischenzeitlich können die Rechner jedoch untereinander in inkonsistenten Zuständen sein; der eine hat den alten Preis, der andere den neuen.

Die Idee von verteilten Datenbanken ist nicht neu. Das Verteilen von Daten in relationalen Datenbanksystemen ist aber ein komplexes Thema und stößt schnell an seine Grenzen. Die Replikation jedoch, also das Spiegeln des Datenbestandes auf mehrere Rechner, wird dagegen sehr wohl eingesetzt und sorgt für Hochverfügbarkeit und verhindert Datenverlust. Möchte man Datensätze aber nicht nur spiegeln, sondern tatsächlich aufteilen, kann dies einen Einfluss auf die Performanz des Systems haben. Befindet sich die Zeile einer Buchungstabelle von einer Reisebuchung der Kundin Ute auf einem anderen Rechner als die Zeile mit den Reisedaten zu Utes gebuchter Mittelmeerkreuzfahrt, ist bei einer Anfrage, die einen Verbund dieser beiden Tabellen ausführt, ein Datentransport über das Netzwerk vonnöten. So wie relationale Datenbanksysteme üblicherweise designt werden, also mit normalisierten Tabellen, die über Fremdschlüssel-Primärschlüssel-Beziehungen miteinander in Beziehung stehen, sind ebensolche Verbundabfragen (englisch: Joins) eine der häufigst gestellten Anfragen in gängigen Anwendungen.

In NoSQL-Datenbanksystemen löst man sich nicht nur aufgrund der Schemaflexibilität vom Modell mit Tabellen und Spalten. Viele NoSQL-Systeme lassen sich der Kategorie der Aggregate-oriented Stores zuordnen. Aggregate steht in dem Fall für so etwas wie die Gesamtheit. Die Idee ist, alles was zusammen gehört, auch zusammen zu speichern. In unserer Reisedatenbank könnte man beispielsweise direkt im Datensatz zu einer Reise die Liste der Kunden speichern, die diese Reise gebucht oder sie auf ihren Merkzettel gesetzt haben. Die Art der Speicherung muss natürlich gut überlegt sein. Man könnte nämlich auch die Liste der gebuchten Reisen in einem Personendatensatz speichern. Wie genau man es modelliert, hängt von der Anwendung ab und welche Anfragen diese üblicherweise an die Datenbank stellt. Der große Vorteil der Speicherung als Gesamtheit ist die Vermeidung von Joins. Dadurch können NoSQL-Datenbanken wunderbar auf mehrere Rechner verteilt und Anfragen schnell beantwortet werden. Gleichzeitig muss man sich jedoch von der Speicherung in Tabellen und Spalten verabschieden und offen sein für neue Datenmodelle und Anfragesprachen.

1.2 Klassifizierung

In den letzten Jahren kamen hunderte NoSQL-Datenbankmanageentsysteme auf den Markt. Sie unterscheiden sich in ihrem Datenmodell und in der Art und Weise, wie man als Benutzer Anfragen an das System stellt. Eines haben jedoch viele NoSQL-Datenbankmanageentsysteme gemeinsam: Die meisten sind open-source.

In diesem Kapitel schauen wir uns die vier Klassen an, in die man fast alle NoSQL-Datenbanksysteme einordnen kann. Die ersten drei sind die Key-Value-Datenbanken, Wide-Column-Stores und Dokumentendatenbanken. Diese werden, wie oben beschrieben, auch Aggregate-oriented Stores genannt, da man alles zu einem Datensatz gehörige innerhalb dieses Datensatzes speichert. Die vierte Klasse, die Graphdatenbanken, verfolgen einen anderen Ansatz. Sie verbinden Datensätze untereinander, wie man es aus Knoten und Kanten eines Graphen kennt.

1.2.1 Key-Value-Datenbanken

Man stelle sich eine Tabelle vor, die nur zwei Spalten hat, eine für einen Schlüssel, eine für einen Wert. Genau das sind Key-Value-Datenbanken. Anfragen an diese werden gestellt, wie man es aus Maps, HashMaps, Dictionaries oder assoziativen Arrays in Programmiersprachen kennt: GET k liefert den Wert zum Schlüssel k, SET k 5 setzt k auf fünf. Mehr Möglichkeiten bei der Speicherung hat man, wenn man den Schlüssel aus mehreren Elementen zusammensetzt, z. B. könnte der Wert des Schlüssels pers/12/name der Name einer Person mit der ID zwölf sein. Viele Key-Value-Stores ermöglichen neben simplen Datentypen wie Zahlen und Zeichenketten die Verwendung komplexer Typen wie Listen und Maps als Werte. Somit kann ein einziges Key-Value-Paar auch einen kompletten Personendatensatz repräsentieren und nicht nur den Namen einer Person. Key-Value-Stores eignen sich für die verteilte Speicherung riesiger Datenmengen und beantworten Anfragen extrem schnell. Jedoch sind Key-Values-Stores in ihrer Anfragemächtigkeit stark eingeschränkt und dienen in der Regel keineswegs als vollständigen Ersatz zu einer relationalen Datenbank. Stattdessen werden sie hauptsächlich zur Performanz-Steigerung für ganz bestimmte Anwendungsszenarios eingesetzt, z. B. zu Caching-Zwecken. Zwei berühmte Key-Value-Stores sind Redis und Riak.

1.2.2 Wide-Column-Stores

„A database administrator walks into a NoSQL bar, but he turns and leaves because he couldn’t find a table.“

Der Witz ist für Wide-Column-Stores nicht ganz wahr. Hier gibt es Tabellen, die aus Zeilen und Spalten bestehen. Allerdings unterscheiden sie sich stark von Tabellen in relationalen Datenbanken. Die Definition der Spalten und deren Datentypen erfolgt hier nämlich nicht beim Erstellen der Tabelle, sondern erst beim Einfügen und Ändern der Daten. Jede Einfügeoperation kann beliebige Spalten setzen, auch wenn es diese Spalte noch gar nicht gibt. Unterschiedliche Zeilen können somit unterschiedliche Spalten haben. Um die Konzepte verschiedener Anwendungsteile innerhalb ein und derselben Tabelle zu speichern, werden Spaltenfamilien (Column Families) zur Aufteilung der Spalten definiert. Eine Personentabelle könnte beispielsweise eine Spaltenfamilie info besitzen, in der alle Information zu einer Person zu finden sind, sowie die Spaltenfamilie kinder, in der in jeder Spalte die ID eines Kindes der Person steht. Diese Modellierung wird beim Datenbanksystem Apache HBase verwendet, welches die freie Implementierung von Google Big Table ist. In HBase setzt oder ändert man den Namen einer Person mit der Row-IDp1 mit put ’pers’, ’p1’, ’info:name’, ’Uwe’. Ein anderer berühmter Wide-Column-Store ist beispielsweise Cassandra.

1.2.3 Dokumentendatenbanken

MongoDB, das Datenbanksystem, von dem dieses Buch handelt, ist eine Dokumentendatenbank. Mit Dokumenten sind hier nicht Word- oder PDF-Dokumente gemeint, sondern im Falle von MongoDB JSON-ähnliche Dokumente. JSON steht für JavaScript Object Notation und ermöglicht eine textuelle Beschreibung von Datensätzen, die aus beliebigen Attributen bestehen können (diese werden Felder genannt). Die Werte von Feldern können von simplen Typen, also Zahlen oder Zeichenketten, oder komplexen Typen wie Listen oder Subdokumenten sein. Bei JSON-Dokumenten handelt es sich um semistrukturierte Daten. Anders als unstrukturierte Daten (wie der Text dieses Buches) haben sie eine Struktur. Aber anders als strukturierte Daten in relationalen Datenbanken ist diese Struktur ein Teil der Daten selbst. Das heißt, das Datenschema muss nicht im Vorhinein festgelegt werden. Weitere Details zu JSON stehen in Kapitel 2.1.5. Eine andere berühmte Dokumentendatenbank ist beispielsweise CouchDB.

1.2.4 Graphdatenbanken

Alle drei bisher vorgestellten Klassen haben eines gemeinsam: Der Zugriff auf einen Datensatz erfolgt über einen eindeutigen Schlüssel, also so etwas wie eine ID. In Key-Value-Datenbanken erfolgt der Zugriff über den Key, in Wide-Column-Stores über die Row-ID und in Dokumentendatenbanken über eine Dokument-ID (in MongoDB heißt dieses Feld _id). In Graphdatenbanken jedoch erfolgt der Zugriff auf die Daten auf eine navigierende Art und Weise: Eine Anfrage startet entweder in einem bestimmten Knoten oder in einer Menge von Knoten und navigiert sich von diesen über Kanten, die die Knoten miteinander verbinden, zu ihren Nachbarn. Es gibt also Knoten und Kanten. Und beide können sogannte Labels und Properties besitzen. Labels geben an, um was für eine Art Knoten oder Kante es sich handelt. In einem sozialen Netzwerk könnten Knotenlabels person oder beitrag sein und Kantenlabels verfasst, gefällt, kommentiert oder ist_Freund. Properties sind ähnlich wie die Felder in Dokumentendatenbanken. Sie erweitern Knoten und Kanten um Attribut-Wert-Paare. Ein Knoten mit dem Label person könnte beispielsweise die Properties name:’Franka’ und geboren:2007 besitzen. Der Knoten könnte mit einer Kante mit dem Label ist_Freund und dem Kanten-Property seit:2016 mit einem anderen Personen-Knoten verbunden sein. Spezielle Anfragesprachen wie Gremlin und Cypher erlauben komplexe Anfragen auf solchen Property-Graphen. Das berühmteste Graphdatenbanksystem ist Neo4J.

1.3 Verteilte Datenbanken

Viele der oben gezeigten Beispiele für NoSQL-Datenbanken sind sogenannte verteilte Datenbankmanagemensysteme. Sie verteilen die Daten auf mehreren Rechnern, um selbst bei riesigen Datenmengen Anfragen und Berechnungen schnell ausführen zu können. Und sollte man dennoch irgendwann an die Grenzen kommen, lässt sich die Performanz durch Hinzufügen weiterer Rechner im Rechencluster einfach und günstig noch weiter erhöhen. Das flexible Hinzufügen von Rechenknoten wird Scaleout genannt. Im Gegensatz dazu bedeutet Scale-up, dass die Leistung durch Aufrüstung einzelner Rechner gesteigert wird, also mehr RAM, bessere CPUs, Festplatten und so weiter. Ein Scale-up ist nur begrenzt möglich und oft sehr teuer, weil dazu meist spezielle Hardware vonnöten ist. Der Scale-out-Ansatz sieht so aus, dass man sich einen Cluster aus vielen Computern zusammenstellt, die aus einfachen und günstigen Standardhardware-Komponenten bestehen, und man je nach Bedarf einfach mehr oder weniger davon einsetzt. Vor allem, wenn ein Unternehmen gar kein eigenes Rechenzentrum betreibt, sondern lediglich Ressourcen in der Cloud mietet, ist ein flexibles Hinzu- und Wegschalten von Rechnern innerhalb weniger Minuten erledigt. So kann beispielsweise ein Online-Shop vor dem großen Ansturm in der Weihnachtszeit einige Rechner mehr einsetzen als davor. Und wenn der Ansturm wieder nachlässt, kann wieder auf Normalbetrieb zurückgefahren werden.

Ein zentrales Konzept in verteilten Datenbanken nennt sich Replikation. Darunter versteht man, dass die gespeicherten Daten gespiegelt werden. Jeder Datensatz liegt also nicht nur auf einem einzigen Rechner, sondern Kopien davon auf mindestens noch einem weiteren. Speichert man 1 Terabyte Daten unter der Verwendung von Replikationsfaktor 3 - jeder Datensatz ist also auf drei Rechnern gespeichert -, belegen diese also insgesamt 3 TB Platz. Die Vorteile von Replikation sind Hochverfügbarkeit, Lastverteilung