Schema-Management in NoSQL

Werbung
Hochschule Darmstadt
- Fachbereich Informatik -
Schema-Management in
NoSQL-Datenbanksystemen
Abschlussarbeit zur Erlangung des akademischen Grades
Master of Science (M.Sc.)
vorgelegt von
Helena Glatzel
Referentin:
Korreferentin:
Prof. Dr. Uta Störl
Prof. Dr. Inge Schestag
Ausgabedatum:
02.10.2013
Abgabedatum:
02.04.2014
Erklärung
Ich versichere hiermit, dass ich die vorliegende Arbeit selbständig verfasst und
keine anderen als die im Literaturverzeichnis angegebenen Quellen benutzt habe.
Alle Stellen, die wörtlich oder sinngemäß aus veröffentlichten oder noch nicht
veröffentlichten Quellen entnommen sind, sind als solche kenntlich gemacht.
Die Zeichnungen oder Abbildungen in dieser Arbeit sind von mir selbst erstellt
worden oder mit einem entsprechenden Quellennachweis versehen.
Diese Arbeit ist in gleicher oder ähnlicher Form noch bei keiner anderen
Prüfungsbehörde eingereicht worden.
Darmstadt, den 02.04.2014
___________________________________________________
(Helena Glatzel)
I
Abstract
In der Anwendungsentwicklung finden sich mittlerweile immer kürzere ReleaseZyklen, auf die auch im Bereich der Datenbanken entsprechend reagiert werden
muss. Gerade im Umfeld der Webanwendungen erfreuen sich daher NoSQLDatenbanksysteme zunehmender Beliebtheit. Durch deren Schema-Flexibilität
kann effizient auf die schnellen Änderungen von Anwendung und Datenschema
eingegangen werden.
Üblicherweise ist es in NoSQL-Systemen nicht erforderlich im Voraus ein Schema
zu definieren. Dieses ergibt sich implizit durch die Struktur der Daten und muss
nicht gesondert definiert und verwaltet werden. Dadurch können jederzeit flexibel
Änderungen am Schema vorgenommen werden.
Allerdings bedeutet dies auch, dass die Verwaltung des Schemas zum Großteil in
der
Verantwortung
der
Anwendung
liegt.
Um
die
Komplexität
der
Anwendungsentwicklung zu begrenzen, ist ein gewisses Maß an Unterstützung
durch das eingesetzte Datenbanksystem wünschenswert.
Diese Arbeit gibt daher einen Überblick über die momentane Unterstützung des
Schema-Managements
durch
die
gängigsten
NoSQL-Datenbanken
und
vielversprechendsten zusätzlichen Entwicklungen. Zu diesem Zweck werden
anhand eines zuvor definierten Anforderungskataloges die sechs meist genutzten
NoSQL-Systeme sowie sechs erweiternde Aufsätze analysiert.
Im Anschluss werden die gewonnenen Erkenntnisse genutzt, um eine SchemaManagement-Komponente zu entwerfen. Diese erfüllt sämtliche Aufgaben des
Schema-Managements und ist systemunabhängig einsetzbar.
II
Abstract
In application development release cycles are getting shorter and shorter which
also leads to some consequences for databases. Especially in web applications
NoSQL databases are gaining more popularity. Due to their schema flexibility, an
efficient reaction to fast changes of applications and database schemas is
possible.
Usually, in NoSQL-systems it is not necessary to define a schema upfront. The
schema is implicitly described by the data itself and does not need to be defined
and managed explicitly. Thereby, schema changes can be performed very flexible
at any time.
However, this means the application has to take responsibility for the schema
management. In order to limit the complexity of application development a certain
level of support by the database system would be desirable.
This thesis gives an overview of the support of schema management supplied by
the most established NoSQL Databases and most promising developments. For
this purpose the six most popular NoSQL systems and six other Tools are
analysed using a requirements catalogue that was defined beforehand.
The gathered informations is used afterwards to design a schema management
component. This component is able to fulfill all schema management tasks and
can be used independently from a certain database system.
III
Inhaltsverzeichnis
Abbildungsverzeichnis......................................VI
Tabellenverzeichnis.......................................VIII
1 Einleitung.................................................1
1.1 Motivation............................................... 1
1.2 Zielsetzung..............................................2
1.3 Struktur der Arbeit.........................................2
2 Grundlagen............................................... 4
2.1 Definition des Begriffs Schema................................4
2.2 Definition Schema-Management...............................4
2.3 Eager vs. Lazy Migration....................................5
2.4 Arten von NoSQL-Datenbanken...............................6
2.4.1 Column Family Datenbanken..............................6
2.4.2 Document Datenbanken................................. 7
2.4.3 Key/Value Datenbanken.................................8
2.4.4 Graphdatenbanken.....................................9
3 Status Quo Analyse........................................10
3.1 Anforderungen an ein Schema-Management.....................10
3.2 Datenmodell und Schema-Management in ausgewählten NoSQLDatenbanksystemen..........................................12
3.2.1 HBase.............................................12
3.2.2 Cassandra..........................................20
3.2.3 BigTable............................................ 28
3.2.4 Google App Engine Datastore............................ 28
3.2.5 MongoDB........................................... 35
3.2.6 CouchDB...........................................44
3.2.7 Couchbase.......................................... 53
3.2.8 Gesamtüberblick NoSQL-Datenbanksysteme.................60
IV
3.3 Aktuelle Entwicklungen im Bereich des Schema-Managements.......64
3.3.1 KijiSchema.......................................... 64
3.3.2 Mongoose.......................................... 75
3.3.3 Hibernate Object/Grid Mapper............................81
3.3.4 Kundera............................................89
3.3.5 Objectify-Appengine................................... 96
3.3.6 JSON Schema...................................... 103
3.3.7 Gesamtüberblick aktueller Entwicklungen...................111
3.4 Ergebnisse der Analysen..................................114
4 Modulare Schema-Management-Komponente...................117
4.1 Anforderungen an die zu entwerfende Schema-Management-Komponente
........................................................117
4.2 Entwurf der Schema-Management-Komponente.................119
4.2.1 Architektur......................................... 119
4.2.2 Technische Konzeption................................ 124
4.2.3 Umsetzung......................................... 127
5 Fazit und Ausblick........................................ 142
5.1 Fazit.................................................142
5.2 Ausblick.............................................. 143
6 Literatur................................................144
V
Abbildungsverzeichnis
Abbildung 1: Beispiel einer Column Family Datenbank....................6
Abbildung 2: Beispiel eines JSON-Dokuments..........................7
Abbildung 3: Ausschnitt Timeline-Table, [Cas-12].......................22
Abbildung 4: Physisches Layout der Timeline-Table in Cassandra, [Cas-12]. . .23
Abbildung 5: Beispiel eines Avro-Schemas für eine User-Entity.............66
Abbildung 6: Beispiel für die Definition einer Existenzbedingung in Mongoose. .77
Abbildung 7: Realisierung eines Composite-Keys in OGM [OGM-13c]........84
Abbildung 8: Beispiel der Speicherung von Beziehungen in OGM mit der
Konfiguration IN_ENTITY [OGM-13c]...............................85
Abbildung 9: Kundera Architektur, [Kun-14c].......................... 89
Abbildung 10: Kundera Annotation-to-NoSQL-Mapping, [Kun-14d]..........90
Abbildung 11: Beispiel für List Validation in JSON Schema [JSc-13g]........105
Abbildung 12: Beispiel für Tupel Validation in JSON Schema [JSc-13g]......105
Abbildung 13: Beispiel-Definition eines Objektes in JSON Schema.........106
Abbildung 14: Eingliederung der Schema-Management-Komponente als externe
Schicht.................................................... 120
Abbildung 15: Schichten-Architektur der Schema-Management-Komponente..122
Abbildung 16: Architektur der Schema-Management-Komponente.........123
Abbildung 17: UML-Klassendiagramm der Doctor Who-Datenbank mit den beiden
Entity-Typen InkarnationDesDoktors und Schauspieler..................128
Abbildung 18: Beispielhafte JSON Schema-Definition der beiden Entity-Typen
InkarnationDesDoktors und Schauspieler...........................129
Abbildung 19: Erweiterung des Meta-Schemas.......................131
Abbildung 20: Beispielhafte JSON Schema-Definition der beiden Entity-Typen
InkarnationDesDoktors und Schauspieler nach Einführung des Meta-Schemas 132
Abbildung 21: Beispiel Insert-Statement, angelehnt an SQL bzw. CQL. . . . . .135
Abbildung 22: Beispiel-Entity vom Typ InkarnationDesDoktors............135
Abbildung 23: Erweitertes UML-Klassendiagramm der Doctor Who-Datenbank mit
den Entity-Typen InkarnationDesDoktors, Schauspieler und Begleiter.......137
VI
Abbildung 24: JSON Schema-Definition des Entity-Typs InkarnationDesDoktors
nach der Durchführung von Schema-Updates........................139
Abbildung 25: Beispiel-Entity vom Typ InkarnationDesDoktors nach der
Durchführung von Schema-Updates...............................140
VII
Tabellenverzeichnis
Tabelle 1: Überblick der von HBase erfüllten Anforderungen an ein SchemaManagement.................................................19
Tabelle 2: Überblick der von Cassandra erfüllten Anforderungen an ein SchemaManagement.................................................27
Tabelle 3: Überblick der von GAE Datastore erfüllten Anforderungen an ein
Schema-Management.......................................... 34
Tabelle 4: Überblick der von MongoDB erfüllten Anforderungen an ein SchemaManagement.................................................43
Tabelle 5: Überblick der von CouchDB zur Verfügung gestellten GET-Calls zur
Abfrage der Schemainformationen, [CDB-14d, CDB-14e, CDB-14f, CDB-14g,
CDB-14h]................................................... 48
Tabelle 6: Überblick der von CouchDB erfüllten Anforderungen an ein SchemaManagement.................................................52
Tabelle 7: Überblick der von Couchbase erfüllten Anforderungen an ein SchemaManagement.................................................59
Tabelle 8: Gesamtüberblick der von den analysierten NoSQL-Systemen erfüllten
Anforderungen an ein Schema-Management..........................63
Tabelle 9: Überblick der von KijiSchema zur Verfügung gestellten DDL-Befehle zur
Schema-Evolution, [Kij-14e, Kij-14f]................................72
Tabelle 10: Überblick der von KijiSchema erfüllten Anforderungen an ein SchemaManagement.................................................74
Tabelle 11: Überblick der von Mongoose erfüllten Anforderungen an ein SchemaManagement.................................................80
Tabelle 12: Überblick der von Hibernate OGM erfüllten Anforderungen an ein
Schema-Management.......................................... 88
Tabelle 13: Von Kundera unterstützte JPQL-Konstrukte nach NoSQL-Systemen,
[Kun-14f]....................................................93
Tabelle 14: Überblick der von Kundera erfüllten Anforderungen an ein SchemaManagement.................................................95
VIII
Tabelle 15: Überblick der von Objectify-Appengine erfüllten Anforderungen an ein
Schema-Management.........................................102
Tabelle 16: Überblick der von JSON Schema erfüllten Anforderungen an ein
Schema-Management.........................................110
Tabelle 17: Gesamtüberblick der von den analysierten aktuellen Entwicklungen
erfüllten Anforderungen an ein Schema-Management...................113
Tabelle 18: Gesamtüberblick der Analyseergebnisse....................116
IX
1
Einleitung
1.1
Motivation
Gerade im heutigen Web 2.0-Umfeld findet man in der Anwendungsentwicklung
immer kürzere Release-Zyklen. Dies wirkt sich auch auf Datenbanken und die
Struktur der Daten aus. Es ist nicht mehr möglich im Vorfeld ein festes Schema zu
definieren, das nur wenigen Änderungen unterliegt und über viele Releases stabil
bleibt.
Um
diesen
Eigenschaften
gerecht
zu
werden,
eignen
sich
NoSQL-
Datenbanksysteme, denn die Schemaflexibilität bzw. Schemalosigkeit wird als
eines ihrer Kern-Features betrachtet [Tiw-11]. Im Gegensatz zu relationalen
Datenbanksystemen muss in den meisten NoSQL-Systemen a priori kein Schema
definiert werden. Dies bedeutet jedoch nicht automatisch das komplette Fehlen
eines Schemas. Die Daten selbst weisen implizit ein Schema auf, selbst wenn
dieses nicht explizit modelliert wird.
Weiterhin verhalten sich NoSQL-Datenbanken hinsichtlich Schema-Änderungen
sehr flexibel. Es ist beispielsweise jederzeit problemlos möglich Objekten neue
Eigenschaften zuzuweisen. Da außerdem die Heterogenität von Objekten
unterstützt wird, können sich die Schema-Änderungen bei Bedarf auf ein einziges
Objekt beschränken und müssen nicht wie in relationalen Datenbanken für die
gesamte Tabelle vorgenommen werden. Dadurch können zwei Objekte der selben
(logischen) Klasse durch vollkommen unterschiedliche Attribute beschrieben
werden.
Die Verwaltung des Schemas obliegt in NoSQL-Datenbanksystemen im Normalfall
der Anwendung. Diese Übertragung der Verantwortung für das SchemaManagement
bringt
Datenbanksystemen
zusammen
eine
mit
neue
der
Ebene
Schemaflexibilität
der
von
Komplexität
NoSQLin
die
Anwendungsentwicklung. Da Anwendungen mit jeglichen Varianten von Objekten
1
umgehen können sollen, ist viel Eigenentwicklung (Custom Programming)
erforderlich. Dies ist sowohl kosten- und zeitintensiv als auch fehleranfällig. Daher
wäre eine (teilweise) Automatisierung des Schema-Managements und somit eine
tiefergehende
Unterstützung
seitens
der
NoSQL-Datenbanksysteme
wünschenswert.
1.2
Zielsetzung
Die Erarbeitung eines Überblicks der derzeitigen Unterstützung des SchemaManagements in NoSQL-Datenbanksystemen ist eines der Hauptziele dieser
Arbeit. Zu diesem Zweck sind zunächst die Anforderungen zu identifizieren, die an
ein Schema-Management gestellt werden. Anschließend werden die sechs
wichtigsten NoSQL-Systeme anhand dieser Kriterien analysiert.
Zusätzlich sind die vielversprechendsten, aktuellen Entwicklungen in diesem
Bereich zu ermitteln. Diese werden, basierend auf den gleichen Kriterien,
ebenfalls untersucht.
Als zweites Hauptziel ist im Anschluss eine modular aufgebaute SchemaManagement-Komponente zu entwerfen. Diese soll sämtliche Aufgaben des
Schema-Managements erfüllen können. Da von der Komponente möglichst viele
verschiedene Systeme unterstützt werden sollen, ist die Unabhängigkeit vom
Datenbanksystem bei dem Architekturentwurf zwingend zu berücksichtigen.
1.3
Struktur der Arbeit
Im Anschluss an das einleitende erste Kapitel werden im zweiten Kapitel die
relevanten Grundlagen beschrieben. Es werden verschiedene Begriffsdefinitionen
erläutert sowie die Kategorisierung von NoSQL-Datenbanksystemen vorgestellt.
Das
darauffolgende
Anforderungskataloges
dritte
die
Kapitel
Analysen
enthält
neben
ausgewählter
der
Definition
NoSQL-Systeme
eines
und
zusätzlicher Entwicklungen im Bereich des Schema-Managements.
2
An diesen Teil schließt sich der Entwurf einer Schema-Management-Komponente
im vierten Kapitel an. Zunächst wird der Anforderungskatalog um einige
zusätzliche Kriterien erweitert. Danach werden die Architektur, Technische
Konzeption und Umsetzung der Komponente beschrieben.
Im abschließenden fünften Kapitel erfolgt ein rückblickendes Fazit auf die
erarbeiteten Ergebnisse sowie ein Ausblick auf mögliche zukünftige Arbeiten zu
diesem Thema.
3
2
Grundlagen
2.1
Definition des Begriffs Schema
Unter dem Begriff Datenbank-Schema ist eine strukturelle Beschreibung der
Datenbank zu verstehen. Dies umfasst zum einen die Definition verschiedener
Entity-Typen und ihrer jeweiligen Eigenschaften, also ihren Attributen (Properties).
[EN-05]
Zum anderen werden im Schema auch Bedingungen bezüglich der Properties
festgelegt. Auf diese Weise kann z.B. der Wertebereich eingeschränkt werden.
Das kann durch die Angabe eines bestimmten Datentyps oder andere
weitergehende Einschränkungen erfolgen. Aber auch die Einzigartigkeit (unique)
oder Existenz (not null) eines Attributes kann definiert werden. [EN-05]
Des Weiteren werden in einem Schema Beziehungen zwischen gleichen und
unterschiedlichen Entity-Typen bzw. zwischen deren Properties festgelegt. [EN-05]
Außerdem erfolgt beim Hinzufügen bzw. Ändern von Daten eine Validierung gegen
das definierte Schema, um sicher zu stellen, dass sich die Datenbank in einem
gültigen Zustand befindet. [EN-05]
2.2
Definition Schema-Management
Das Schema-Management umfasst neben der eigentlichen Modellierung sowohl
die Schema-Extraktion basierend auf einer vorhandenen, mit Objekten gefüllten
Datenbank, als auch die Schema-Evolution, also das Management der späteren
Weiterentwicklungen des Schemas. Außerdem muss die erforderliche Migration
vorhandener Daten unterstützt werden. Im besten Fall werden sowohl Eager als
auch Lazy Migration angeboten.
4
2.3
Eager vs. Lazy Migration
Unter eager Migration ist die Anpassung aller Datensätze an das neue Schema
nach einer Schema-Änderung zu verstehen. Dies ist relativ aufwendig und kann
unter Umständern sogar eine Downtime des Systems erfordern. Allerdings kann
auf diese Weise sichergestellt werden, dass nach Abschluss der Migrationsroutine
alle Datensätze dem neuen Schema entsprechen.
Lazy Migration führt die Migration eines Datensatzes erst dann durch, wenn das
erste mal nach einer Schema-Änderung auf ihn zugegriffen wird. Dies hat den
Vorteil, dass keine Downtime des Systems notwendig ist. Außerdem werden durch
lazy Migration überflüssige Migrationen vermieden. Werden in einer Datenbank
beispielsweise Blog-Einträge verwaltet, so wird auf ältere Einträge nicht mehr oder
nur noch selten zugegriffen. Diese Einträge müssen daher nicht an das neue
Schema angepasst werden und verbleiben in der ursprünglichen Schema-Version.
Allerdings müssen Anwendungen sowohl die alte als auch neue Version des
Schemas unterstützen. Soll ein veraltetes Schema irgendwann als ungültig erklärt
werden, muss für die bis zu diesem Zeitpunkt noch nicht migrierten Daten eine
eager Migration durchgeführt werden, um sicher zu stellen, dass alle Daten dem
neuen Schema entsprechen und weiterhin von der Anwendung verarbeitet werden
können.
Theoretisch ist auch eine dritte Variante denkbar. Es ist auch möglich, dass sowohl
alte und neue Schema-Version nach einem Schema-Update erhalten bleiben. In
diesem Fall ist keinerlei Migration erforderlich. Lediglich Anwendungen müssen so
angepasst werden, dass sie (dauerhaft) mit beiden Versionen umgehen können.
5
2.4
Arten von NoSQL-Datenbanken
2.4.1
Column Family Datenbanken
Eine Column Family Datenbank kann als Menge von verschachtelten Maps
betrachtet werden, die üblicherweise als Row bezeichnet und über einen Row-Key
eindeutig identifiziert wird. Die Keys der Key/Value-Paare werden als Columns
bezeichnet. [EFH-11]
Beliebig viele Columns werden in sogenannten Column Families gruppiert.
Column Families werden physisch zusammenhängend gespeichert und müssen
normalerweise im Vorfeld definiert werden. Die Columns einer Family sollten
logisch miteinander in Verbindung stehen. Dies ist jedoch keine Voraussetzung,
sondern dient der besseren Performanz der Abfragebearbeitung, da davon
auszugehen ist, dass diese Daten häufig gemeinsam abgefragt werden. [EFH-11]
Für jede Row werden nur die Columns gespeichert, in denen tatsächlich Werte
vorhanden sind. Null-Werte wie in einem relationalen Datenbanksystem werden
nicht gespeichert. [Tiw-11]
Abbildung 1: Beispiel einer Column Family Datenbank
6
Üblicherweise gibt es in Column-Family-Systemen kein Update im klassischen
Sinn, sondern es werden multiple Versionen jeder Row gespeichert. Die Rows
selbst werden in der Datenbank nach dem Row-Key sortiert abgelegt. [Tiw-11]
Die bekanntesten Column-Family-Datenbanken sind Google BigTable, HBase und
Cassandra. Wobei die beiden letzteren Systeme nach dem Vorbild von BigTable
entwickelt wurden. [RW-12]
2.4.2
Document Datenbanken
Document Datenbanken sind nicht zu verwechseln mit klassischen DokumentManagement-Systemen. Unter Dokumenten sind strukturierte Sammlungen von
Key/Value-Paaren z.B. in Form von JSON- oder BSON-Dokumenten zu verstehen.
Die Values können üblicherweise einen vom Dokumentformat unterstützten
Datentyp annehmen oder ebenfalls wieder ein Dokument bzw. eine Menge von
Dokumenten
sein.
Also
werden
auch
beliebig
tief
verschachtelte
Dokumentstrukturen unterstützt. [RW-12]
Document Datenbanken speichern die (JSON-/ BSON-) Dokumente zusammen
mit einer identifizierenden ID und ermöglichen Indexe basierend sowohl auf der
Dokument-ID als auch auf anderen Keys. [Tiw-11]
{
"id": 1,
"Vorname": "Christina",
"Nachname": "Schmidt",
"Adresse": {
"Strasse": "Bahnhofstraße",
"Hausnummer": "7a",
"PLZ": 64283,
"Ort": "Darmstadt"
}
}
Abbildung 2: Beispiel eines JSON-Dokuments
Systemabhängig können Dokumente ggf. in Collections gruppiert werden. Ähnlich
7
wie bei Column Families sollten diese gruppierten Dokumente zwecks
Performanceverbesserung der Abfrage als auch zur Unterstützung effektiver
Indexierung möglichst ähnlich sein. Dies ist allerdings keine bindende Vorgabe. Es
können theoretisch beliebig verschiedene Dokumente in einer Collection gruppiert
werden. [EFH-11]
Bekannte Vertreter dieser NoSQL-Datenbank-Kategorie sind MongoDB, CouchDB
und Couchbase. [EFH-11]
2.4.3
Key/Value Datenbanken
Key/Value Datenbanken nutzen ein sehr einfaches Datenmodell. In ihnen werden,
wie der Name bereits vermuten lässt, einfache Key/Value-Paare gespeichert.
Dieses einfache Datenmodell ermöglicht sehr schnelle Zugriffszeiten. Komplexe
Abfragen können im Normalfall nicht vom System unterstützt werden, da dieses
keinerlei Informationen über Typ oder Struktur des Values hat. [RW-12]
Es gibt jedoch eine Vielzahl von Key/Value-Datenbanken - Redis, Riak oder
Berkeley DB seien als kleine Auswahl genannt - die verschiedene, zusätzliche
Features bieten. Je nach System können auch Hashes, Listen oder sogar JSONDokumente als Value gespeichert werden. Des Weiteren werden systemabhängig
auch diverse Datenzugriffsmethoden bereitgestellt. [EFH-11]
Durch die fehlenden Informationen über Value-Typ und -Struktur ist nicht davon
auszugehen, dass Key/Value-Datenbanken eine Unterstützung des SchemaManagements zur Verfügung stellen können. Daher werden im Rahmen dieser
Arbeit keine Systeme dieser Kategorie betrachtet.
8
2.4.4
Graphdatenbanken
Der Vollständigkeit halber seien an dieser Stelle ebenfalls Graphdatenbanken
erwähnt.
Im
weiteren
Verlauf
der Arbeit
werden
diese
aufgrund
ihrer
Andersartigkeit zu Datenbanksystemen der vorherigen drei Kategorien jedoch
nicht weiter betrachtet.
In Graphdatenbanken werden Graph- oder Baumstrukturen mit Beziehungen
zwischen deren Knoten verwaltet. Sowohl Knoten als auch Kanten können mit
Key/Value-Paaren zur Beschreibung weiterer Eigenschaften ergänzt werden. [RW12] Der herausstechende „Vorteil der Graphdatenbanken ist daher natürlich, die
Relationen viel schneller traversieren zu können, als dies z.B. auf einer
relationalen Datenbankstruktur möglich wäre“ [EFH-11, S. 9].
Das bekannteste Datenbanksystem dieser Kategorie ist Neo4j. [EFH-11]
9
3
Status Quo Analyse
Nachfolgend wird eine Menge an Anforderungen an ein Schema-Management
definiert. Diese bauen auf typischen Eigenschaften eines Schema-Managements
in relationalen Datenbanksystemen sowie [SKS-13] auf. Die Analysen der
betrachteten NoSQL-Datenbanken und zusätzlicher Aufsätze im weiteren Verlauf
dieses Kapitels erfolgen anhand dieser Kriterien.
3.1
Anforderungen an ein Schema-Management
● Es wird eine geeignete Möglichkeit zur Schemabeschreibung und
-speicherung benötigt. Basierend auf der Definition des Begriffs Schema
aus 2.1 müssen die nachfolgenden Eigenschaften beschrieben werden
können:
•
verschiedene Entity-Typen
•
Struktur der Entity-Typen (Properties)
•
Einschränkungen der Properties
–
Dies umfasst die Unterstützung der benötigten Datentypen (die
konkreten Datentypen sind datenbankabhängig)
–
Die
weitergehende
Einschränkung
des
Wertebereiches
auf
bestimmte Wertgrenzen (z.B. Value between 0 and 10) sollte
ebenfalls beschrieben werden können
–
Außerdem gehört dazu auch die Möglichkeit Eigenschaften wie
Einzigartigkeit (unique) oder Existenz (required, not null) festlegen zu
können.
•
Kennzeichnung einer Property als Primary Key
•
Beziehungen zwischen gleichen und unterschiedlichen Entity-Typen
bzw. deren Properties
● Schema-Extraktion
•
Ableiten des Schemas auf Basis des existierenden Datenbestandes
10
● Schema-Evolution
folgende Operationen zur Schemamanipulation müssen bereitgestellt
werden: [vgl. SKS-13]
•
Hinzufügen eines neuen Entity-Typs zum Schema
•
Löschen eines Entity-Typs aus dem Schema
•
Umbenennen eines Entity-Typs
•
Update eines Entity-Typs
- Hinzufügen eines Attributes (add property)
- Löschen eines Attributes (delete property)
- Umbenennen eines Attributes (rename property)
- Verschieben eines Attributes von einem Entity-Typ zu einem anderen
(move property)
Kopieren eines Attributes von einem Entity-Typ zu einem anderen
(copy property)
● Es sollte eine Validierung gegen das Schema erfolgen
● Die Koexistenz mehrerer, ggf. parallel gültiger Schema-Versionen sollte
unterstützt werden
● Eine Unterstützung der Datenmigration wäre wünschenswert
•
Eager Migration
•
Lazy Migration
11
3.2
Datenmodell
und
Schema-Management
in
ausgewählten NoSQL-Datenbanksystemen
3.2.1
HBase
HBase gehört zur Kategorie der Column-Family-NoSQL-Datenbanken. Als OpenSource-Klon von Googles BigTable ist es laut [EFH-11] und [HBa-13a] ein
spaltenorientiertes Datenbanksystem zur verteilten, versionierten Speicherung
großer Mengen semistrukturierter Daten.
HBase speichert Daten in Tabellen. Diese bestehen aus Zeilen (eine Zeile = ein
Datensatz) und Spalten (Properties). Jede Zeile hat einen eindeutigen Row-Key,
über den sie identifiziert wird und über den jegliche Datenzugriffe erfolgen. Die
Daten werden in HBase nach dem Row-Key, der nicht geändert werden kann,
sortiert. Daher ist das Row-Key-Design ein wichtiger Punkt der Schema-Definition.
[HBa-13b]
HBase gruppiert Spalten in Column Families. Jede Spalte muss einer Column
Family zugeordnet werden. Die Daten einer Column Family werden physisch
zusammenhängend
gespeichert.
Es
ist
außerdem
möglich
bestimmte
Eigenschaften der Column Families zu spezifizieren, z.B. die Anzahl der zu
speichernden Versionen. Diese Metadaten werden allerdings nur für Tabellen und
Column Families verwaltet. Bezüglich Columns kennt HBase keine Metadaten.
[HBa-13b, HBa-13c] Laut [HBa-13c] sollten nicht mehr als zwei bis drei Column
Families genutzt werden, da andernfalls die Performance deutlich abnehmen
kann.
Sowohl Tabellen als auch Column Families sollten im Vorfeld bei der SchemaDefinition angelegt werden. Es existiert aber auch die Möglichkeit im späteren
Verlauf Column Families bzw. deren Metadaten zu ändern oder neue Column
Families hinzuzufügen. Dies ist üblicherweise jedoch sehr kostenintensiv. Im Fall
der Änderung von Metadaten muss HBase beispielsweise eine neue Column
12
Family mit den neuen Parametern erzeugen und anschließend alle Daten
kopieren. [RW-12]
Die Möglichkeit Online-Schema-Updates durchzuführen gibt es seit der Version
0.92.x [HBa-13c]. Ob dies unterstützt wird, kann in der HBase-Konfiguration
festgelegt werden. Standardmäßig ist die Online-Durchführung von SchemaUpdates möglich. [HBa-13d]
Im Gegensatz zu Column Families ist das Hinzufügen neuer Columns generell
problemlos, jederzeit zur Laufzeit möglich, sofern die zugehörige Column Family
bereits definiert wurde. Dies geschieht durch einfaches Einfügen eines
Datensatzes mit neuer Column. [EFH-11]
In HBase sind Datensätze unveränderbar. Da jede Zeile durch Hinzufügen eines
Timestamps (explizit angegeben oder von HBase automatisch generiert)
versioniert wird, führen Update-Operationen nicht zum Überschreiben des „alten“
Datensatzes, sondern es wird eine neuere Version der Zeile erzeugt. [Tiw-11]
HBase unterstützt, bezogen auf ihre Columns, heterogene Datensätze. Daher ist
der einzige Weg, alle Columns, die zu einer Tabelle oder Column Family gehören,
zu finden, ein Full-Table-Scan. [HBa-13b]
Mittlerweile werden von HBase auch Constraints unterstützt. So kann z.B. der
zulässige Wertebereich eines Column-Values eingegrenzt werden. Eine weitere
Einsatzmöglichkeit wäre es mittels Constraints die referentielle Integrität der Daten
sicherzustellen. Dies sollte allerdings in der Praxis nicht genutzt werden, da es mit
großer Wahrscheinlichkeit den Schreibdurchsatz stark reduzieren würde. [HBa13c]
Verschiedene Datentypen, wie aus relationalen Datenbanksystemen bekannt,
werden von HBase nicht unterstützt. Alle Daten, auch die Row-Keys, werden als
uninterpretierte Byte-Arrays gespeichert. Die Validierung zu speichernder Werte
13
muss, genauso wie die Umwandlung gelesener Daten in den jeweiligen Datentyp,
auf Anwendungsebene realisiert werden. [RW-12]
HBase ist also relativ flexibel hinsichtlich der Schemaorganisation, jedoch kein
komplett schema-freies System. Allerdings hat sich HBase mittlerweile zu einem
flexibleren System entwickelt. Mit der Unterstützung von Online-Schema-Updates
müssen nur noch Tabellen zwingend im Voraus definiert werden. Column Families
können bei Bedarf auch zur Laufzeit, ohne Downtime, eingefügt oder geändert
werden.
Ein eigenes, explizites, integriertes Schema-Management wird nicht von HBase
zur Verfügung gestellt.
Wie bereits weiter oben erläutert speichert HBase Metadaten zu Tabellen und
Column Families. [HBa-13b] Ob dies zur Verwaltung von Entity-Typen ausreichend
ist, hängt von der konkreten Modellierung ab. So können unterschiedliche EntityTypen, wie auch in relationalen Modellen, z.B. als verschiedene Tabellen
gespeichert werden. Aber auch die Nutzung von Column Families zur
Repräsentation von Entity-Typen oder anderer Varianten ist denkbar.
Eine tiefergehende Modellierung der Entity-Typen ist allerdings nicht realisierbar,
da HBase keine Metadaten zu Columns verwaltet [HBa-13b]. Somit ist es nicht
möglich die konkrete Struktur von Entities im Schema zu modellieren. Dies
umfasst logischerweise neben der grundsätzlichen Modellierung von Properties
der Entity-Typen auch sämtliche zusätzlichen Informationen über diese Properties
(Einschränkungen, Kennzeichnung als Primary Key und Kennzeichnung von
Beziehungen). Allerdings ist zu erwähnen, dass eine Speicherung der Datentypen
der Properties ohnehin theoretisch unnötig ist, da in HBase alle Daten als ByteArray abgelegt werden.
Konstrukte um Beziehungen zwischen Entity-Typen im klassischen Sinn, wie aus
relationalen Dtenbanksystemen bekannt, zu modellieren, werden von HBase nicht
zur Verfügung gestellt. In HBase existiert keine Unterstützung von Joins oder
14
Foreign Keys. Üblicherweise werden Beziehungen mittels Denormalisierung oder
in der Anwendung verwalteten Referenzen modelliert. [HBa-13b] Da die
Repräsentation von Beziehungen zwischen Entity-Typen bzw. ihren Properties von
der individuellen Umsetzung abhängig ist, bietet HBase keine Möglichkeit diese im
Schema zu definieren.
Ein Datenbankschema beschränkt sich bei HBase also auf Tabellen und ihre
zugehörigen Column Families inklusive deren konfigurierbarer Parameter. Um
eine auch nur annähernd vollständige Schema-Beschreibung zu erstellen, sind
diese Möglichkeiten natürlich bei weitem nicht ausreichend.
Eine weitere Anforderung, die ein Schema-Management erfüllen sollte, ist die
Schema-Extraktion, um aus einer existierenden, gefüllten Datenbank ein Schema
abzuleiten. Auch in diesem Fall bietet HBase nur wenig Unterstützung.
Es existiert die Möglichkeit die von HBase gespeicherten Metadaten auszulesen.
Daher können Informationen sowohl zu Tabellen als auch zu den jeweils
zugehörigen Column Families ausgelesen werden. Dies kann z.B. über den
HTableDescriptor und den HColumnDescriptor der Java-API erfolgen.
[vgl. HBa-13e, HBa-13h]
Da zu den Columns keinerlei Metadaten gespeichert werden, muss, wie schon im
Vorfeld erwähnt, ein Full-Table-Scan durchgeführt werden, um alle Columns, die
zu einer Tabelle gehören, zu ermitteln. [HBa-13b]
Die von HBase bereitgestellten Möglichkeiten der Schema-Beschreibung können
also aus einer bestehenden, mit Daten gefüllten Datenbank extrahiert werden.
Allerdings sind, wie oben erläutert, diese Schema-Informationen sehr begrenzt
und umfassen lediglich Metadaten zu Column Families und Tabellen.
Als dritte wichtige Anforderung an ein Schema-Management wurde in 3.1 die
Unterstützung der Schema-Evolution genannt. Ob das Hinzufügen und Löschen
15
eines Entity-Typs von HBase unterstützt wird, ist von der Art und Weise wie EntityTypen in der konkreten Modellierung repräsentiert werden abhängig.
In jedem Fall gibt es die Möglichkeit sowohl Tabellen als auch Column Families
neu anzulegen oder zu löschen.
Eine neue Tabelle kann beispielsweise mit der createTable(...)-Methode des
HBaseAdmin der Java-API hinzugefügt werden. Ebenso ist das Löschen einer
Tabelle mittels der deleteTable(...)-Methode möglich. [HBa-13f] Das
Umbenennen einer Tabelle wird von HBase nicht unterstützt und muss in der
Anwendung geschehen. Hierfür bietet HBase die Möglichkeit eines Snapshots der
Datenbank. [HBa-13j]
Das
Hinzufügen
einer
neuen
Column
Family
kann
z.B.
über
die
addColumn(...)-Methode des HBaseAdmin der Java-API erfolgen. Analog
kann
zur
Löschung
einer
Column
Family
beispielsweise
die
deleteColumn(...)-Methode des HBaseAdmin genutzt werden. [HBa-13f] Das
Umbenennen einer Column-Family wird von HBase nicht unterstützt.
Die Möglichkeit Properties der Entities im Schema zu verändern (alle unter 3.1
genannten Varianten inklusive Hinzufügen und Löschen) existiert nicht, da HBase
hierzu keinerlei Informationen im Schema speichert [HBa-13b] und diese somit
auch nicht im Zuge der Schema-Evolution geändert werden können.
Zumindest die wenigen von HBase verwalteten Schema-Informationen werden zur
Validierung eingesetzt. So ist es nicht möglich Daten einzufügen oder zu ändern,
ohne dass die angesprochene Tabelle bereits existiert. Ebenso können keine
Daten gespeichert werden, deren Columns nicht einer bestimmten Column Family
zugeordnet werden. Gleichermaßen wird es nicht unterstützt, Daten in die
Datenbank zu schreiben, ohne dass die Column Family bereits angelegt wurde.
Das Einfügen von Daten erfolgt über die Put-Operation. Mittels Put wird eine neue
Version einer Zelle gespeichert. Eine Zelle wird identifiziert durch die Tabelle zu
16
der sie gehört, sowie durch den Row-Key, die Column Family, die Column und den
Timestamp. Daher sind alle diese Informationen beim Einfügen von Daten
anzugeben. Beim Versuch die Operation mit unvollständigen Parameterangaben
durchzuführen, kommt es zu einer Fehlermeldung. Einzige Ausnahme bildet der
Timestamp. Er kann wahlweise auch von HBase generiert werden und muss nicht
zwingend angegeben werden. [HBa-13b, HBa-13i]
Eine weitergehende Validierung kann nicht erfolgen, da HBase keine SchemaInformationen zur Struktur der Entity-Typen speichert und so natürlich die Daten
nicht entsprechend überprüft werden können. Eine solche Art der Validierung
muss innerhalb der Anwendung realisiert werden.
Mehrere Schema-Versionen, im besten Fall parallel gültige, werden von HBase
nicht unterstützt. Ein HBase-Schema besteht nur aus Metadaten zu Tabellen und
Column Families. Eine Historisierung der Schema-Änderungen existiert nicht.
Weiterhin ist es nicht möglich, dass parallel verschiedenen Tabellen oder Column
Families nur für einen Teil der Daten existieren.
Aufgrund der wenigen von HBase verwalteten Schema-Informationen gibt es im
Grunde nur zwei Schema-Änderungen bei denen eine Datenmigration in Frage
kommt. Wird eine Tabelle neu angelegt, existieren noch keine Daten für die eine
Migration notwendig wäre. Beim Löschen einer Tabelle werden die enthaltenen
Daten ebenfalls gelöscht und müssen nicht migriert werden.
Somit sind im Hinblick auf die Datenmigration nur das Hinzufügen und Löschen
einer Column Family zu betrachten. Wird eine neue Column Family angelegt,
existiert diese automatisch (zumindest theoretisch) für alle Rows, auch wenn der
jeweilige Datensatz (noch) keine Columns in dieser Family speichert. Analog wird
eine Column Family beim Löschen für alle Rows gelöscht, unabhängig davon ob
ein konkreter Datensatz Columns in dieser Family gespeichert hat oder nicht. Zu
beachten ist, dass die in der gelöschten Column Family gruppierten Columns
zusammen mit der Column Family gelöscht werden. [HBa-13b, HBa-13f] Dieses
17
Verhalten ist allerdings nicht ausreichend, um es als (teilweise) Unterstützung der
Datenmigration seitens HBase zu werten.
Eine Unterstützung der Datenmigration bei Änderung der Struktur eines EntityTyps kann von HBase aufgrund der fehlenden Metadaten nicht zur Verfügung
gestellt werden. Eine solche Migration muss von der Anwendung angestoßen und
gesteuert werden.
Als Ergebnis dieser Analyse kann gesagt werden, dass HBase nur wenig
Mechanismen zum Schema-Management bietet. Es fehlt schon alleine eine
Möglichkeit ein Schema bis in die benötigte Tiefe, inklusive Struktur und weiteren
Eigenschaften der Entities, zu beschreiben. Aus diesem Grund können auch die
weiteren unter 3.1 genannten Anforderungen an ein Schema-Management nicht
oder nur unzureichend erfüllt werden. In Tabelle 1 sind die Analyseergebnisse
abschließend zusammengefasst.
18
Feature
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
Kennzeichnung als Primary Key
Beziehungen
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
unterstützt
(✓)
(✓)
Column Families (CF)
modellierungsabhängig, Tabellen &
Column Families (CF)
(✓)
(✓)
Nur Metadaten
(✓)
(✓)
X
X
X
X
X
X
X
Einfügen neuer CF / Tabelle möglich
(✓)
X
Unterstützung der Datenmigration
X
Lazy Migration
Metadaten zu Tabellen &
X
X
X
X
Mehrere Schema-Versionen
Eager Migration
Erläuterung
modellierungsabhängig
Löschen von CF / Tabelle möglich
Keine Modellierung von Properties
Nur Metadaten, keine Validierung
gegen Entity-Struktur
Beim Löschen von Tabelle/ CF
werden Daten auch gelöscht
X
X
Tabelle 1: Überblick der von HBase erfüllten Anforderungen an ein Schema-Management
19
3.2.2
Cassandra
Cassandra gehört genauso wie HBase zur Kategorie der Column Family
Datenbanksysteme, verfolgt aber einen hybriden Ansatz. Vorbild für Cassandra
waren Amazon Dynamo (Key/Value-Store) und Googles BigTable. Ziel hierbei ist
es „einerseits eine größtmögliche Flexibilität und Skalierbarkeit und andererseits
auch eine durch SQL-Datenbanken vertraute Schemasicherheit“ [EFH-11, S. 82]
zu bieten. [EFH-11, Tiw-11]
Oberste Struktureinheit ist der Keyspace. Ein Keyspace ist vergleichbar mit der
Datenbank in der Welt der relationalen Datenbanksysteme. Er kapselt alle
anwendungsrelevanten Daten. Unter einem Keyspace lassen sich Column
Families definieren. [EFH-11] Der Begriff Column Family meint in Cassandra
allerdings nicht das Gleiche wie in HBase oder BigTable, sondern ist mit einer
Tabelle in einem relationalen System vergleichbar. In der Cassandra Query
Language (CQL) wird mittlerweile anstelle von Column Family der Begriff Table
genutzt. Teilweise wird aber auch noch der Begriff Column Family synonym zu
Table verwendet. [Cas-14a]
Eine Tabelle (Column Family) enthält eine Menge von Rows, die über einen
eindeutigen Schlüssel identifiziert werden. [Cas-14a] Tabellen können mit diversen
Eigenschaften, z.B. Compaction- und Compression-Eigenschaften, konfiguriert
werden. [CQL-13a]
Cassandra bietet die Möglichkeit zu jeder Tabelle einen Metadatensatz zu
hinterlegen. Dieser definiert sowohl den Datentyp (Cassandra arbeitet mit
spezifischen Datentypen wie ASCII, bigint, blob,...) der einzelnen Columns als
auch eventuelle zusätzliche Indexe. Jedoch wird hierdurch nicht definiert, dass
diese Columns in einer Row enthalten sein müssen, sondern nur dass die
beschriebene Column den angegebenen Datentyp haben muss, falls die Column
in einer Row überhaupt existiert. Beim Einfügen von Daten werden alle Columns
nach dem Namen sortiert. [EFH-11]
20
Da Cassandra genauso wie HBase eine automatische Versionierung mitbringt,
bestehen Columns im einfachsten Fall aus 3-Tupeln aus Name, Wert und
Timestamp [CQL-14a]. Timestamps können explizit angegeben oder von
Cassandra generiert werden [CQL-13b].
Für die Datendefinition und -manipulation bietet Cassandra mit der Cassandra
Query Language (CQL) eine sehr umfangreiche, SQL-ähnliche Sprache. Im
Gegensatz zu HBase müssen in Cassandra nicht nur Keyspace und Table im
Vorfeld
angelegt
werden.
Sollen
Daten
eingefügt
angegebenen Spalten zuerst mittels ALTER
TABLE
werden,
ADD
müssen
die
column_name
column_type dem Schema hinzugefügt werden, falls sie nicht bereits mit
Erzeugung der Tabelle angelegt wurden. Allerdings ist es möglich Tabellen und
Columns jederzeit zur Laufzeit zu erzeugen oder zu ändern, ohne dass Updates
und Queries blockiert werden. [CQL-13a, CQL-14b]
Abfragen lassen sich in Cassandra nur auf Indexen ausführen. Falls es sich um
eine Abfrage mit mehreren Kriterien handelt, muss das erste Kriterium auf eine
indexierte Column bezogen sein. Daher werden von Cassandra Secondary
Indexes unterstützt. [EFH-11] Ein Secondary Index auf einer existierenden Column
lässt sich mit dem Statement CREATE INDEX ON table_name(column_name)
erzeugen. Existieren bereits Daten in der angegebenen Column, werden diese
automatisch asynchron indexiert. Werden neue Daten in der Column gespeichert,
fügt Cassandra beim Einfügen automatisch einen neuen Indexeintrag hinzu. [CQL13a]
Damit Daten bei Bedarf stärker strukturiert werden können, gibt es in Cassandra
sogenannte Composite Columns. Diese können mittels Compound Primary Key
eine tiefere Verschachtelung bieten. Ein Compound Primary Key nutzt mehr als
eine
Column
als
Identifizierungsmerkmal.
Hier
ist
die
Reihenfolge
der
angegebenen Columns entscheidend. Die erste Column wird als Partition Key
bezeichnet und als Primary Key der Row genutzt. Die weiteren Columns werden
Clustering Columns genannt. Sie bestimmen die Sortierreihenfolge mit der
Cassandra die Rows speichert. Intern werden alle Datensätze mit dem selben
21
Partition Key physikalisch als eine einzige Row gespeichert. Mit Hilfe der
Clustering Columns kann so eine beliebige Verschachtelungstiefe erreicht werden.
[Cas-12, CQL-13a]
Das nachfolgende Beispielszenario aus [Cas-12] verdeutlicht die Anwendung von
Composite Columns zur Realisierung weiterer Strukturierungsebenen.
In der Tabelle „Timeline“ sollen Tweets für Follower verwaltet werden. Hierfür
werden User_Id, Tweet_Id, Author und Inhalt des Tweets (= body) gespeichert.
Mittels Primary Key (user_id, tweet_id) wird der Compound Primary
Key definiert. Bei einem neuen Tweet wird für jeden Follower ein entsprechender
Eintrag inklusive einer Kopie des Tweets in der Timeline gespeichert. Abbildung 3
zeigt einen Beispiel-Ausschnitt der Timeline-Tabelle.
Abbildung 3: Ausschnitt Timeline-Table, [Cas-12]
Intern speichert Cassandra in diesem Beispiel, wie in Abbildung 4 dargestellt, zwei
Rows, jeweils eine pro eindeutiger user_id, und erzeugt so eine neue
Strukturierungsebene.
22
Abbildung 4: Physisches Layout der Timeline-Table in Cassandra, [Cas-12]
Im Gegensatz zu HBase ist Cassandra relativ inflexibel hinsichtlich des Schemas.
Ähnlich zu relationalen Systemen müssen sowohl Keyspace und Table als auch
Columns vor dem Einfügen von Daten im Schema definiert werden. Jedoch
verhält sich Cassandra nicht so strikt wie man es von relationalen Systemen
kennt. Das definierte Schema legt nicht fest, dass jede Row die beschriebenen
Columns enthalten muss. Es wird lediglich definiert, welche Columns genutzt
werden können. Somit kann Cassandra dank relativ umfangreicher Metadaten viel
Unterstützung für das Schema-Management bieten und trotzdem eine gewisse
Schema-Flexibilität bewahren, die von NoSQL-Systemen erwartet wird.
Ob die von Cassandra verwalteten Metadaten zur Modellierung von Entity-Typen
und ihrer Struktur ausreicht, ist auch in Cassandra abhängig von der konkreten
Umsetzung. Es ist z.B. möglich die unterschiedlichen Entity-Typen mittels
verschiedener Tabellen zu repräsentieren. Da Metadaten zu den Columns
gespeichert werden, ist es auf diese Art und Weise möglich auch die Struktur der
Entity-Typen im Schema darzustellen. Die Datentypen der Columns werden
ebenfalls von Cassandra im Schema verwaltet. Weitere Einschränkungen der
Properties (Columns), wie etwa die Einschränkung auf einen bestimmten
Wertebereich, werden nicht von Cassandra unterstützt. [CQL-13a, CQL-14c]
Es ist allerdings möglich bzw. sogar erforderlich eine oder mehrere Column/s als
Primary Key zu kennzeichnen. Dies geschieht während der Tabellendefinition.
Besteht ein Primary Key aus nur einer Column, kann diese direkt nach Angabe
ihres Datentyps als Primary Key spezifiziert werden (CREATE Table t (key
int PRIMARY KEY, otherColumn text) ). Handelt es sich um einen
Compound Primary Key, der aus mehreren Columns besteht, muss der Schlüssel
23
im Anschluss an die Column-Definitionen mittels PRIMARY KEY(column_1,
column_2, …) spezifiziert werden. [CQL-13a]
Beziehungen zwischen verschiedenen Entity-Typen und/ oder ihren Properties
werden in Cassandra nicht unterstützt. Es existieren keine Joins oder Foreign
Keys. Logische Beziehungen werden üblicherweise per Denormalisierung oder mit
Hilfe von Collection Columns (Listen u.ä.) realisiert. Daher können Beziehungen
nicht im Schema modelliert werden. [CQL-14b]
Mit den von Cassandra gespeicherten Metadaten lässt sich ein Schema
weitgehend beschreiben. Es ist möglich Entity-Typen inklusive ihrer Struktur,
Datentypen der Properties und Angabe des Primary Keys zu modellieren.
Lediglich weitergehende Einschränkungen der Properties und Beziehungen lassen
sich nicht mit den von Casandra angebotenen Mitteln verwalten.
Die von Cassandra verwalteten Schema-Informationen lassen sich aus einer
gefüllten Datenbank auch wieder extrahieren. Dies kann z.B. über eine Query auf
die von Cassandra verwalteten System Tables realisiert werden (SELECT * FROM
system.schema_columnfamilies). [CQL-14c]
Alternativ können Metadaten auch mit Hilfe der entsprechenden get-Methoden der
Klassen TableMetadata und ColumnMetadata der Java-API (z.B. des
Datastax Java Treibers) extrahiert werden. [Cas-13a, Cas-13b]
Da sich im Laufe der Zeit das Schema weiterentwickelt, ist es wichtig, dass die
Schema-Evolution vom Schema-Management unterstützt wird. Inwieweit die in
3.1 definierten Anforderungen von Cassandra erfüllt werden, ist abhängig von der
konkreten Modellierung der Entity-Typen. Ausgehend von der Annahme, dass
verschiedene Entity-Typen in unterschiedlichen Tabellen gespeichert werden,
können einige der Anforderungen aus 3.1 von Cassandra erfüllt werden.
Es ist möglich mit dem CREATE TABLE-Kommando der CQL neue Tabellen zu
erzeugen, sowie mittels DROP TABLE existierende Tabellen inklusive der darin
24
enthaltenen Daten zu löschen. [CQL-13a] Das Umbenennen einer Tabelle wird in
Cassandra nicht unterstützt. In früheren Versionen wurde dieses Feature
angeboten, allerdings wieder entfernt, da das Umbenennen von Tabellen (und
Keyspaces) sehr fehleranfällig war. Mittlerweile ist es nur noch manuell durch
Erzeugen einer neuen Tabelle, Kopieren sämtlicher Daten und Löschen der alten
Tabelle realisierbar. [Cas-13c]
Da Cassandra Metadaten zu Columns speichert, gibt es auch die Möglichkeit im
Zuge der Schema-Evolution die Struktur der Entity-Typen zu verändern. Um
Columns, die zum Zeitpunkt der Erzeugung einer Tabelle noch nicht angelegt
wurden, zu einer Tabelle hinzuzufügen wird das
ALTER
TABLE
ADD
column_name column_type -Kommando der CQL genutzt. Wird anstelle von
ADD die Instruktion DROP gewählt, können mit dem ALTER TABLE-Kommando
Columns aus dem Schema einer Tabelle gelöscht werden. Das Umbenennen von
Columns muss, genauso wie das Verschieben oder Kopieren einer Column in eine
andere Tabelle, in der Anwendung erfolgen. Cassandra bietet hier keine
Unterstützung. [CQL-13a]
Die von Cassandra verwalteten Schema-Informationen werden auch zur
Validierung genutzt. Bei dem Versuch einen bereits existierenden Keyspace oder
eine existierende Tabelle erneut anzulegen, kommt es zu einer Fehlermeldung,
sofern nicht die Option IF NOT EXISTS genutzt wird. In diesem Fall wird die
Operation nicht ausgeführt, falls der Keyspace/ die Tabelle schon existiert.
Gleiches gilt für das Löschen von Keyspace und Tabelle mit der Option IF
EXISTS. Ebenso ist es nicht möglich Werte mit einem invaliden Datentyp in
Columns einzufügen. [CQL-13a]
Mehrere ggf. sogar parallel gültige Schema-Versionen werden von Cassandra
nicht unterstützt, da bei Schema-Änderungen die Metadaten der Tabelle bzw. des
Keyspaces geändert werden. Es ist z.B. auch nicht möglich, dass eine Column
mehrere verschiedene, gültige Datentypen besitzt. [CQL-13a]
25
Da mit den im Schema von Cassandra verwalteten Column-Metadaten, keine
Existenzbedingung (abgesehen von den Primary Key-Columns) einhergeht und
auch kein entsprechendes Constraint unterstützt wird, gibt es keine SchemaEvolutions-Operationen für die eine Datenmigration erfolgen muss. Beim
Hinzufügen eines neuen Entity-Typs existieren noch keine Daten, die migriert
werden müssten. Beim Löschen eines Entity-Typs werden die Daten zusammen
mit der Tabelle gelöscht. Mit dem Hinzufügen oder Löschen einer Column ist auch
keine Datenmigration notwendig, da Columns, die im späterem Verlauf dem
Schema hinzugefügt werden, nicht Teil des Primary Keys und daher für jede Row
optional sind. Wie beim Löschen eines Entity-Typs werden auch beim Löschen
einer Column die Daten dieser Column gelöscht. Das Mitlöschen der Daten beim
Entfernen von Entity-Typ bzw. Column kann allerdings noch nicht als (teilweises)
zur Verfügung Stellen einer automatischen Datenmigration gewertet werden.
Cassandra bietet also einige Unterstützung des Schema-Managements. So
können zum Beispiel Entity-Typen inklusive Struktur und Primary Key im Schema
modelliert werden. Dennoch können, wie Tabelle 2 zusammenfassend zeigt, nicht
alle Anforderungen an ein Schema-Management aus 3.1 erfüllt werden.
26
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
Kennzeichnung als Primary Key
Beziehungen
(✓)
(✓)
✓
X
(✓)
Schema-Evolution
(✓)
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
Mehrere Schema-Versionen
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
zu
Keyspace,Tabellen
und Columns
✓
✓
Schema-Extraktion
Add Entity-Type
Metadaten
✓
✓
X
(✓)
✓
✓
X
X
X
Datentypen unterstützt, aber keine
weiteren Einschränkungen
Single/ Compound Primary Key
Auslesen
aller
verwalteter
Metadaten möglich
Einfügen neuer Tabelle
Löschen einer Tabelle
Einfügen neuer Column
Löschen einer Column
✓
X
X
X
X
Tabelle 2: Überblick der von Cassandra erfüllten Anforderungen an ein SchemaManagement
27
3.2.3
BigTable
Googles BigTable ist Vorreiter im Bereich der NoSQL-Datenbanken und gehört zur
Kategorie der Column-Family-Systeme. HBase und Cassandra nahmen sich
BigTable als Vorbild, daher entspricht die Datenmodellierung in BigTable der oben
unter HBase beschriebenen Umsetzung. Allerdings handelt es sich bei BigTable,
anders als bei HBase oder Cassandra, um ein Closed Source System. [Tiw-11]
Aus diesen beiden Gründen wird BigTable an dieser Stelle nicht weitergehend
betrachtet.
3.2.4
Google App Engine Datastore
Google App Engine (GAE) ist Googles Cloud Plattform zur Entwicklung und dem
Betrieb von Webanwendungen. Es werden verschiedenen Programmiersprachen
wie z.B. Java, Python oder PHP unterstützt. Google stellt u.a. eine Untermenge
der Standard-APIs JDO (Java Data Objects) oder JPA (Java Persistence API) zur
Anwendungsentwicklung zur Verfügung. Entwickler können so wie gewohnt mit
Entities und Beziehungen arbeiten. [GAE-13a]
Momentan existieren drei Varianten der Datenspeicherung im Google App Engine
Umfeld. Zum einen der Google App Engine Datastore, der auf dem NoSQLDatenbanksystem BigTable basiert. Zum anderen Google Cloud SQL, ein
relationaler Datenbankservice basierend auf MySQL, sowie Google Cloud
Storage, ein Objekt- und Dateispeicherdienst. [GAE-13a, EFH-11] Im Folgenden
wird nur der GAE Datastore betrachtet, da die beiden anderen Varianten im
Rahmen dieser Arbeit nicht relevant sind.
Im GAE Datastore werden Entities, die eine oder mehrere Properties haben,
gespeichert. Im Gegensatz zu BigTable arbeitet der GAE Datastore mit
spezifischen Datentypen für die Property-Values. Eine Entity wird durch einen
Entity-Typ und einen Key eindeutig identifiziert. Optional kann eine Entity eine
andere Entity als Parent definieren und so eine hierarchische Struktur festlegen.
Entities ohne Parent-Entity werden als Root-Entity bezeichnet. Entities, die zur
gleichen Root-Entity gehören, werden der gleichen Entity-Gruppe zugeordnet. Für
28
Entities einer Gruppe werden atomare Abfragen unterstützt. Schreiboperationen
werden innerhalb von sogenannten Cross-Group-Transaktionen für bis zu fünf
verschiedene Entity-Gruppen als atomare Operation ausgeführt. Der GAE
Datastore unterstützt also auch Transaktionen. [GAE-14a]
Da der GAE Datastore auf BigTable aufbaut, handelt es sich um ein schemaloses
System. Die Entities eines Typs müssen nicht die gleichen Properties haben.
Weiterhin können Properties mehrere Werte, die unterschiedliche Datentypen
haben können (z.B. eine Liste von Values, deren Datentypen sich unterscheiden),
besitzen. Es ist auch möglich, dass zwei Entities für gleiche Properties
verschiedene Datentypen definieren. Der GAE Datastore macht keinerlei
Schemavorgaben bezüglich der Struktur von Entities. Falls ein formales Schema
erforderlich ist, ist es Aufgabe der Anwendung die Einhaltung des Schemas
sicherzustellen. [GAE-14a, GAE-14b]
Die nachfolgende Analyse basiert weitestgehend auf der Nutzung von GAE
Datastore mit dem Python SDK (Software Development Kit). Wird ein anderes
SDK, z.B. das Java-SDK, genutzt, ist davon auszugehen, dass die Analyse anders
ausfallen kann und z.B. weniger oder andere Anforderungen an ein SchemaManagement erfüllt werden können.
Das Python App Engine SDK beinhaltet eine Data Modeling Library, mit der
Entities als Instanz einer von drei verfügbaren Modell-Klassen repräsentiert
werden können. In der Python Datastore API wird der Entity-Typ durch diese
Model-Klassen definiert. [GAE-14c]
Zum einen gibt es die model-Klasse, mit der das Daten-Schema, ähnlich wie in
relationalen Systemen, im Voraus festgelegt wird. Es handelt sich also um ein
inflexibles Schema. Auch können hier Existenzbedingungen oder Default-Values
für Properties festgelegt werden. Beim Einfügen von Daten erfolgt eine Validierung
gegen das definierte Schema. [GAE-13b, Tiw-11]
29
Eine weitere Klasse ist expando. Mit ihr können Schemata dynamischer und
flexibler modelliert werden. Es existieren zwei Typen von Attributen. Erstens die
fixed Properties, die wie Properties der model-Klasse a priori definiert werden,
dafür aber auch validiert werden können. Zweitens die dynamic Properties, die zur
Laufzeit mit einer Entity in die Datenbank geschrieben werden, aber nicht validiert
werden können. [GAE-13b, Tiw-11]
Die letzte Schema-Modellierungsklasse heißt polymodel. Mit dieser Klasse ist es
möglich
eine
Hierarchie
zwischen
verschiedenen
Modellierungsklassen
festzulegen. Mittels dieser Hierarchie werden bei einer Abfrage Entities der
angesprochenen
Klasse
sowie
ihrer
Subklassen
in
die
Ergebnismenge
aufgenommen. [GAE-13b, Tiw-11]
Mit Hilfe der verschiedenen Schema-Modell-Klassen kann in Google App Engine
also der Grad der Schemafreiheit flexibel - vom festen, a priori zu definierenden
Schema bis zur kompletten Schemalosigkeit - vom Entwickler festgelegt werden.
Zur Definition und Manipulation sowie der Abfrage von Entities existieren
verschiedene Möglichkeiten. Neben Implementierungen von JDO und JPA stellt
Google App Engine für Python eine SQL-ähnliche Abfragesprache, die Google
Query Language (GQL), zur Verfügung. [Tiw-11]
Jede Abfrage innerhalb des Google App Engine Datastore basiert auf Indexen.
Der GAE Datastore legt automatisch für alle Properties der Entity-Typen einen
Index an. Teilweise müssen zusätzliche Indexe definiert werden, um Queries
effizient ausführen zu können. Indexe werden mit dem Einfügen von Entities oder
der Durchführung von Änderungen an ihnen automatisch aktualisiert. [GAE-13c]
Obwohl der GAE Datastore die schemalose NoSQL-Datenbank BigTable nutzt,
bietet er einige Möglichkeiten des Schema-Managements. So kann z.B. mit den
Python-Model-Klassen ein Schema, mit vom User konfigurierbarer Flexibilität,
angelegt werden.
30
Da GAE Datastore Daten als verschiedene Entity-Typen speichert, ist es
logischerweise möglich eine entsprechende Schema-Beschreibung zu erstellen.
Es werden Metadaten zu Entity-Gruppen, Namespaces, Entity-Typen und
Properties gespeichert. [GAE-13d] Daher ist es auch möglich die Struktur der
Entity-Typen zu modellieren.
Wie bereits oben beschrieben, werden zu den Properties auch Datentypen
hinterlegt. Eine weitere Einschränkung des Wertebereichs ist nur durch Angabe
einer
Liste
möglicher
Werte
(choices=set([„value1“,
„value2“]))
realisierbar. Die Einzigartigkeit von Properties kann nicht im Schema modelliert
werden. Allerdings können Existenzbedingungen mittels required=True im
Schema hinterlegt werden. [GAE-13e]
Standardmäßig wird der Primary Key in dem Property key gespeichert, das nicht
explizit definiert wird. Es ist allerdings möglich anderen Properties diese
Eigenschaft zuzuweisen, indem dem Property-Konstruktor das Argument name
mit
der
Option
übergeben
“key“
wird,
beispielsweise
myEntity_key=db.StringProperty(name=“key“). Zugriffe können dann
mit dem jeweiligen Property-Namen erfolgen. Im Datastore wird der Primary Key
dennoch in dem Feld key gespeichert. [GAE-13e, GAE-13f]
Mit der ReferenceProperty-Klasse stellt GAE Datastore eine Möglichkeit,
Beziehungen zwischen Entities zu modellieren, zur Verfügung. Damit kann einer
Property eine Referenz auf einen bestimmten Entity-Typ zugewiesen werden. Als
Value dieser Property wird automatisch der Key des referenzierten Entities
genutzt. Außerdem wird die automatische Dereferenzierung unterstützt. Der Value
der referenzierenden Property kann genutzt werden, als wäre er eine Instanz der
referenzierten Entity. Mit der Klasse SelfReferenceProperty werden auch
Selbstreferenzen unterstützt. [GAE-13b]
Die von GAE Datastore verwalteten Metadaten können mit Hilfe sogenannter
Helper Functions ausgelesen werden. Die Methode get_kinds(...) kann
beispielsweise
genutzt
werden,
um
alle
Entity-Typen
einer Anwendung
31
abzufragen. Analog dazu liefert die Methode get_properties_of_kind(...)
eine Liste aller indexierter Properties des als Parameter übergebenen Entity-Typs.
Falls nicht im Schema explizit anders konfiguriert, werden alle Properties
automatisch indexiert und sind somit in der Ergebnismenge enthalten. [GAE-13d]
Mit den Helper Functions ist es also möglich aus einer gefüllten Datenbank das
Schema zu extrahieren.
Als weitere wichtige Anforderung an ein Schema-Management sollte weiterhin die
Schema-Evolution
unterstützt
werden.
Auch
hier
stellt
GAE
Datastore
verschiedene Möglichkeiten zur Verfügung.
Ein neuer Entity-Typ kann beispielsweise mit der Python-API als neue ModelKlasse im Code hinzugefügt werden. [GAE-13b] Eine Unterstützung zum Löschen
oder Umbenennen eines Entity-Typs gibt es in GAE Datastore nicht. [Sta-11]
Wird die oben beschriebene Expando-Model-Klasse genutzt, ist es möglich zur
Laufzeit Properties durch Einfügen eines Entities, mit den jeweiligen neu
einzufügenden Properties, hinzuzufügen. [GAE-13b]
Weitere Update-Operationen bezüglich der Properties werden nicht von GAE
Datastore unterstützt und müssen in der Anwendung erfolgen. Es gibt zwar die
Möglichkeit Properties zu löschen, aber selbst wenn diese aus der Definition der
Model-Klasse
gelöscht wurden,
können
bereits existierende Entities die
betroffenen Properties weiterhin besitzen. Um die Properties endgültig zu löschen,
müssen sie mittels Full-Table-Scan auf Anwendungsebene in jeder Entity gelöscht
werden. [GAE-12]
Der GAE Datastore nutzt die verfügbaren Metainformationen zur Validierung. So
ist es beispielsweise nicht möglich Entities zu speichern, deren Typ vorher nicht
definiert wurde. Da eine Entity eindeutig durch den Typ und einen Key identifiziert
wird, kommt es zu einer Fehlermeldung, falls der Entity-Typ nicht existiert. [GAE14a]
32
Werden die Model-Klassen model oder expando genutzt, erfolgt eine
automatische Validierung gegen Datentyp und Existenzbedingung der fixed
Properties. [GAE-13b]
Mit Hilfe der verwalteten Metadaten zu fixed und dynamic Properties der
Expando-Modell-Klasse werden von GAE Datastore mehrere, parallel gültige
Schema-Versionen unterstützt. Beispielsweise können zwei Entities des selben
Typs gleiche Properties mit unterschiedlichen Datentypen besitzen. Allerdings
erfolgt keine Validierung gegen die dynamischen Properties.
Eine automatische Datenmigration steht in GAE Datastore nicht zur Verfügung.
Auch bei Änderungen der fixed Properties eines Entity-Typs werden existierende
Entities nicht automatisch angepasst. Werden beispielsweise neue Properties mit
einem Default-Wert hinzugefügt, haben zwar alle neu eingefügten Entities diese
Properties mit entsprechendem Value, bereits existierende Entities werden
allerdings nicht automatisch migriert und müssen in der Anwendung mittels FullTable-Scan angepasst werden. [GAE-12]
GAE Datastore bietet somit relativ umfangreiche Mittel zur Beschreibung von
Entity-Typen
und
ihren
Properties.
Es
wird
sogar
eine
automatische
Dereferenzierung von Beziehungen zur Verfügung gestellt. Dennoch fehlt, wie in
Tabelle 3 ersichtlich, vor allem eine Unterstützung der Schema-Evolution.
33
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
✓
✓
✓
(✓)
Kennzeichnung als Primary Key
✓
Beziehungen
✓
Schema-Extraktion
✓
Schema-Evolution
(✓)
(✓)
X
X
X
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
Mehrere Schema-Versionen
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
✓
X
X
X
X
✓
(✓)
Datentypen, Existenzbedingung &
Liste akzeptierter Werte
Metadaten
zu
Entity-Typen
und
Properties verfügbar
mittels neuer Model-Klasse im Code
z.B. Nutzung von Expando-Klasse
gegen Entity-Typ, fixed Properties:
Datentyp, required-constraint
Durch dynamische Properties und
Property-Metadaten
X
X
X
Tabelle 3: Überblick der von GAE Datastore erfüllten Anforderungen an ein SchemaManagement
34
3.2.5
MongoDB
MongoDB ist der Kategorie der Document Datenbanken zuzuordnen. Der Name
MongoDB ist abgeleitet vom englischen „humongous“ (= riesig) und lässt auf die
Ausrichtung auf die Speicherung von sehr großen Datenmengen schließen. [EFH11]
Daten werden in MongoDB in Form von BSON-Dokumenten gespeichert. Es
werden
alle BSON-Datentypen
unterstützt. Allerdings
können in
BSON-
Dokumenten theoretisch mehrere Felder den selben Namen (=Key) haben. Dies
wird jedoch nicht empfohlen und von den meisten MongoDB Interfaces auch nicht
unterstützt. [Mon-13a, vgl. auch RFC-4627 „The names within an object SHOULD
be unique“]
MongoDB garantiert keine feste, gleichbleibende Speicherreihenfolge der
Key/Value-Paare eines Dokumentes. Die Felder innerhalb eines Dokumentes
können durch spätere Update- oder Einfüge-Operationen umsortiert werden. Um
festzustellen, ob zwei Dokumente die gleiche Struktur aufweisen, mit anderen
Worten die gleichen Key/Value-Paare besitzen, müssen also alle Paare der
Dokumente mittels Full-Table-Scan miteinander verglichen werden. [Mon-13a]
BSON-Dokumente können in MongoDB maximal 16 MB groß sein, damit eine
möglichst effiziente Speicherauslastung erreicht werden kann. Außerdem dient
diese Begrenzung der Einschränkung der benötigten Bandbreite bei der
Übertragung von Dokumenten. Zur Speicherung größerer Dokumente stellt
MongoDB eine Spezifikation namens GridFS zur Verfügung. [Mon-13a]
Dokumente sind vergleichbar mit Tupeln in einer relationalen Datenbank und
werden eindeutig über eine ID, die explizit angegeben oder von MongoDB
generiert werden kann, identifiziert. Die Dokumente werden in sogenannten
Collections gruppiert. [EFH-11, Mon-13a]
35
MongoDB ist ein schemaloses System. Nicht einmal eine Datenbank oder
Collection muss im Voraus definiert werden. Sie werden erst zum Zeitpunkt des
ersten Einfügens eines Dokumentes angelegt. [RW-12]
Verschiedene Dokumente können eine beliebig voneinander abweichende
Struktur aufweisen. Auch Collections schränken Dokumente nicht hinsichtlich ihres
Schemas ein. Dokumente innerhalb der selben Collection müssen nicht die
gleichen Felder besitzen. Dennoch ist es aus Performancegründen sinnvoll,
Dokumente mit ähnlicher Struktur in Collections zu gruppieren. [EFH-11]
In MongoDB gibt es die Möglichkeit die Größe einer Collection zu beschränken.
Solche Collections werden als Capped Collections bezeichnet. Erreicht eine
Capped Collection ihre Maximalgröße, so werden alte Dokumente automatisch
beim Einfügen weiterer Dokumente gelöscht. [Tiw-11] Explizit gelöscht werden
können einzelne Dokumente einer Capped Collection nicht. Es besteht nur die
Möglichkeit die gesamte Capped Collection zu leeren oder komplett zu löschen.
Weiterhin können Dokumente nur dann geändert werden, wenn sich dadurch der
von ihnen benötigte Speicherplatz nicht vergrößert. [Mon-13d]
Indexierung wird von MongoDB in dem Umfang, wie es von relationalen Systemen
bekannt ist, unterstützt. Indexe werden auf Collection-Ebene erstellt. Auf der
Dokument-ID wird automatisch beim Einfügen des Dokumentes ein Index erzeugt.
Weitere Indexe können beliebig vom User angelegt werden. MongoDB unterstützt
hierfür eine Vielzahl von Indexstrukturen, von klassischen B-Bäumen bis zu zweioder mehrdimensionalen Geoindexen. [RW-12]
MongoDB
stellt
eine
eigene,
SQL-ähnliche
Abfragesprache
sowie
eine
Implementierung von Map Reduce zur Verfügung. Die Abfragesprache bietet
allerdings umfangreiche Möglichkeiten in Bezug auf Filter und Selektion, sodass in
vielen Fällen kein Einsatz vom aufwendigeren Map Reduce notwendig ist [EFH11].
36
In mehreren der bisher vorgestellten Datenbanken werden Daten automatisch
versioniert. MongoDB bietet kein solches Feature und Updates werden in-place
ausgeführt. [Mon-13b]
Zur Änderung von Dokumenten existieren zwei Methoden. Der Update-Methode
kann ein Filter übergeben werden, der die zu ändernden Dokumente definiert. Mit
dieser Methode können also mehrere Dokumente mit nur einem Befehl geändert
werden. Je nach übergebenen Parametern ändert diese Methode Werte
bestimmter Felder oder ersetzt das komplette Dokument. [Mon-13b]
Die zweite Variante zur Änderung von Dokumenten ist die Save-Methode. Diese
Methode kann immer nur ein einzelnes Dokument ändern und ersetzt es mit
einem neuen Dokument. Eine Änderung einzelner Felder des existierenden
Dokumentes ist mit dieser Methode nicht möglich. [Mon-13b]
Der markanteste Unterschied der MongoDB-Syntax und SQL sind fehlende JoinOperationen. Joins werden in MongoDB nicht unterstützt und sollten im Normalfall
auch nicht erforderlich sein. [Mon-13c]
Üblicherweise wird in MongoDB, wie in den meisten NoSQL-Systemen, ein
denormalisiertes Datenmodell genutzt und Dokumente verschachtelt gespeichert.
Dies macht es auch möglich mit nur einer einzigen Datenbankoperation ein
Dokument inklusive aller Sub-Dokumente abzufragen oder zu ändern. [Mon-13e]
Dennoch ist es manchmal nützlich, wenn sich Dokumente gegenseitig
referenzieren.
In MongoDB gibt es zwei Möglichkeiten Referenzen zu realisieren. Zum einen gibt
es die Möglichkeit der manuellen Referenzen. Hier wird in einem Dokument die ID
des referenzierten Dokumentes gespeichert und die Anwendung muss sich um die
Auflösung der Referenz kümmern. MongoDB bietet in diesem Fall keine
Unterstützung. [Mon-13c]
37
Die zweite Möglichkeit sind sogenannte DBRefs. Sie bieten ein standardisiertes
Format Referenzen zwischen verschiedenen Dokumenten zu beschreiben. Im
Normalfall werden diese Referenzen allerdings nicht automatisch aufgelöst. In wie
weit die Dereferenzierung tatsächlich unterstützt wird und in welchem Maß die
Anwendung verantwortlich ist, ist treiberabhängig. Daher sind DBRefs nur
empfehlenswert, wenn ein Dokument auf mehrere Dokumente aus verschiedenen
Collections referenziert. [Mon-13c]
Als schemaloses NoSQL-System bietet MongoDB also viele Features, die in
relationalen Datenbanksystemen üblich sind. Jedoch mit dem Vorteil, dass im
Voraus kein Schema zu definieren ist und jederzeit flexibel Änderungen am
Schema durch simples Einfügen neuer Daten vorgenommen werden können. Ein
explizites Schema-Management wird jedoch nicht von MongoDB angeboten.
Verschiedene Metadaten werden von MongoDB in sogenannten System
Collections
gespeichert.
In
der
systems.indexes-Collection
werden
Informationen zu allen Indexen verwaltet. Die system.namespaces-Collection
enthält Metadaten zu allen Collections. Weitere Metadaten zum Namespace
werden in der .ns-Datei abgelegt. [Mon-13f]
Ob diese Metadaten zur Beschreibung von Entity-Typen ausreichen, ist wie auch
schon in vorherigen Systemen abhängig von der konkreten Modellierung. Es ist
denkbar, dass die verschiedenen Entity-Typen durch unterschiedliche Collections
repräsentiert
werden.
Aber
auch
andere
Modellierungsvarianten
können
umgesetzt werden. Die Struktur von Entity-Typen nähergehend zu modellieren ist
in MongoDB nicht möglich, da keine Metadaten zu einzelnen Dokumenten bzw.
ihren Feldern verwaltet werden.
Eine Möglichkeit zumindest indirekt einige Feldinformationen in MongoDB zu
verwalten wäre es, Indexe zu nutzen. Die zu Indexen gespeicherten Metadaten
enthalten auch Informationen zu den indexierten Feldern. Diese aus den
Metadaten zu extrahieren müsste jedoch auf Anwendungsebene erfolgen.
38
Auf diese Weise wäre es auch möglich die Einzigartigkeit von Properties mittels
Erzeugung eines Unique Index auf dem entsprechendem Feld zu verwalten.
Durch den Unique Index wird sichergestellt, dass keine Dokumente in die
Datenbank eingefügt werden, deren Wert des indexierten Feldes bereits innerhalb
eines anderen, schon in der Datenbank gespeicherten, Dokumentes vorkommt.
[Mon-13g] Aber auch in diesem Fall müsste die Information von der Anwendung
aus den Index-Metadaten extrahiert werden.
Eine tatsächliche Modellierung von Entity-Strukturen und Einschränkungen der
Properties ist also mit MongoDB nicht möglich. Daher wird eine Kennzeichnung
von Properties als Primary Key ebenfalls nicht unterstützt. Allerdings ist dies
theoretisch auch nicht notwenig, da MongoDB den Feldnamen _id für den Primary
Key reserviert. [Mon-13a]
Wie oben beschrieben bietet MongoDB mit DBRefs zwar eine standardisierte
Möglichkeit Referenzen zwischen Dokumenten zu kennzeichnen, jedoch handelt
es sich hierbei um eine konkrete Referenz innerhalb eines bestimmten
Dokumentes. Metadaten zu DBRefs werden nicht verwaltet. Darüber hinaus
müssen andere Dokumente des gleichen Entity-Typs nicht notwendigerweise auch
eine solche DBRef enthalten. Daher bietet MongoDB keine Unterstützung, um
Referenzen im Schema zu modellieren.
Ein Schema in MongoDB enthält also Informationen zu Datenbanken, Collections
und Indexen. Eine vollständige Schemamodellierung ist mit diesen beschränkten
Informationen nicht möglich.
Die Extraktion der verwalteten Schema-Informationen aus einer bereits gefüllten
Datenbank wird von MongoDB unterstützt. Metadaten sowohl zu Datenbanken als
auch Collections und Indexen können z.B. über die Klassen MongoClient, DB
und DBCollection der Java-API ausgelesen werden. [Mon-13h, Mon-13i, Mon13j] Da zu den Key/Value-Paaren der Dokumente keine Metadaten gespeichert
werden, muss ein Full-Table-Scan durchgeführt werden, um alle Felder zu
ermitteln.
39
Eine weitere wichtige Anforderung an ein Schema-Management ist die
Unterstützung der Schema-Evolution. In wie weit dies von MongoDB geleistet wird
ist von der konkreten Modellierung der Entity-Typen abhängig.
Ungeachtet dessen ermöglicht MongoDB es Datenbanken und Collections neu
anzulegen und auch zu löschen. Ein explizites Erzeugen von Datenbanken oder
Collections ist in MongoDB allerdings nicht erforderlich. Sie werden von MongoDB
automatisch erstellt, wenn sie das erste Mal in einem Methodenaufruf genutzt
werden. [Mon-13k]
So wird z.B. beim Aufruf der
getDB(String
dbname)-Methode des
MongoClient der Java-API, mit der eine Verbindung zur angegebenen
Datenbank aufgebaut wird, die betroffene Datenbank erzeugt, falls diese noch
nicht
existiert.
Gelöscht
werden
kann
eine
Datenbank
mittels
der
dropDatabase(String dbName)-Methode des MongoClient. [Mon-13h] Ein
von MongoDB unterstütztes Umbenennen der Datenbank gibt es bisher nicht.
[Mon-13n]
Analog dazu wird eine neue Collection z.B. mittels getCollection(String
name)-Methode der DB-Klasse der Java-API erzeugt, falls sie bei diesem
Methodenaufruf noch nicht existiert. Gelöscht werden kann eine Collection durch
Ausführung
der
drop()-Methode
der
DBCollection-Klasse.
Mit
der
rename(...)-Methode der DBCollection-Klasse gibt es die Möglichkeit
Collections umzubenennen [Mon-13i, Mon-13j]
Die verwalteten Entity-Typen darüber hinaus zu verändern wird von MongoDB
nicht unterstützt. Da es keine Möglichkeit gibt die Properties der Entity-Typen zu
modellieren, können auch keine Schema-Änderungen gespeichert werden.
In MongoDB können die einzufügenden Dokumente gegen die BSONSpezifikation validiert werden, um sicher zu stellen dass keine invaliden
Dokumente in die Datenbank eingefügt werden. Bei stark verschachtelten
40
Dokumenten kann sich die Validierung aber negativ auf die Performance
auswirken. [Mon-13l]
Eine weitergehende Validierung gegen ein konkretes Schema muss in der
Anwendung erfolgen und wird nicht von MongoDB unterstützt. Zum einen werden
Datenbanken und Collections automatisch neu angelegt, falls sie beim
Methodenaufruf noch nicht existieren. Zum anderen werden keine tiefergehenden
Metadaten bezüglich des Schemas gespeichert, die zur Validierung genutzt
werden könnten.
Mehrere parallel gültige Schema-Versionen werden von MongoDB nicht
unterstützt, da ein MongoDB-Schema lediglich aus Metadaten zu Datenbanken,
Collections und deren Indexen besteht. Es ist nicht möglich, dass z.B. für
verschiedene Dokumente unterschiedliche Collections zu einer Datenbank
gehören.
Allerdings unterstützt MongoDB Schema-Änderungen teilweise mit automatischer
Migration. Wird eine Datenbank neu erzeugt, existieren noch keine Daten, die
migriert werden müssen. Analog dazu existieren beim Löschen einer Datenbank
auch keine Daten, die für die Migration berücksichtigt werden müssten, denn diese
werden ebenfalls gelöscht. Gleiches gilt für das Erzeugen und Löschen einer
Collection; bzw. wird eine Collection dann erzeugt, wenn zum ersten Mal ein
Dokument eingefügt wird, das aber bereits zu dieser Collection gehört und somit
eine Migration überflüssig macht.
Sollen bereits zu einer anderen Collection gehörende Dokumente in diese neue
Collection eingefügt werden, können z.B. mit der MongoDB-Shell-Methode
copyTo() alle Dokumente einer Collection in eine neue Collection kopiert werden
[Mon-13m]. Das Kopieren von nur einzelnen Dokumente einer Collection zur
neuen Collection muss allerdings auf Anwendungsebene geschehen.
41
Wird eine Collection umbenannt, z.B. durch die rename(...)-Methode der
DBCollection-Klasse der Java-API, werden die Daten automatisch von
MongoDB migriert. [Mon-13j]
Eine Datenmigration bei Änderungen der Struktur der Entity-Typen kann von
MongoDB nicht zur Verfügung gestellt werden, da diesbezüglich keine Metadaten
verwaltet werden. Eine solche Migration muss von der Anwendung ausgehen und
kontrolliert werden.
Abschließend lässt sich sagen, dass auch MongoDB nur wenig Unterstützung für
das
Schema-Management
bietet.
Es
werden
zwar
teilweise
Metadaten
gespeichert, aber da keine Informationen zu den einzelnen Dokument-Feldern
verfügbar sind, ist es schon nicht möglich Entity-Typen mitsamt ihrer PropertyStruktur zu beschreiben. Tabelle 4 gibt einen abschließenden Überblick der
Analyse.
42
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
Kennzeichnung als Primary Key
Beziehungen
(✓)
(✓)
X
X
X
X
Schema-Extraktion
(✓)
Schema-Evolution
(✓)
(✓)
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
(✓)
(✓)
X
X
X
X
X
X
Validierung
X
Mehrere Schema-Versionen
X
Unterstützung der Datenmigration
Collections
Keine Modellierung von Properties
nicht notwendig, _id-Feld reserviert
Zwar DBRefs, aber nicht im Schema
Auslesen
von
Metadaten
zu
Datenbanken, Collections & Indexen
Einfügen neuer Collection
Löschen einer Collection möglich
Umbenennen von Collections
Keine Modellierung von Properties
Validierung gegen BSONSpezifikation möglich
(✓)
Eager Migration
(✓)
Lazy Migration
X
bei Umbenennen/ Löschen/
Kopieren gesamter Collection
Tabelle 4: Überblick der von MongoDB erfüllten Anforderungen an ein SchemaManagement
43
3.2.6
CouchDB
CouchDB gehört wie MongoDB ebenfalls zur Kategorie der Document
Datenbanken. Daten werden in JSON-Dokumenten gespeichert. Collections, wie
zuvor bei MongoDB beschrieben, existieren in CouchDB nicht. Eine vorherige
Schemadefinition ist nicht notwendig und die Struktur der Dokumente kann
jederzeit flexibel geändert werden. Vor dem Einfügen von Dokumenten muss
lediglich die Datenbank, in der diese gespeichert werden sollen, angelegt worden
sein. CouchDB gehört somit auch zu den schemalosen NoSQL-Datenbanken.
[EFH-11]
Die Dokumente werden mittels unveränderbarer, eindeutiger ID und einer
Revisionsnummer identifiziert. CouchDB verfolgt eine Append-only-Strategie.
Dokumente werden nicht wie in MongoDB in-place geändert, sondern eine neue
Version des Dokumentes mit inkrementierter Revisionsnummer gespeichert. Im
Gegensatz zu HBase werden diese verschiedenen Versionen von Dokumenten
nicht dauerhaft gesichert und dienen nur der Parallelisierung der Zugriffe sowie
der Konflikterkennung und -auflösung. Ein Zugriff auf frühere Versionen eines
Dokumentes ist nicht möglich. Mittels der verschiedenen Versionen können
Lesezugriffe über Multiversion Concurrency Control (MVCC) erfolgen und es ist
kein Sperren von Dokumenten notwendig. [Tiw-11]
Die Dokumente können in CouchDB mit Anhängen versehen werden. Anhänge
sind in ihrer Art und ihrem Inhalt nicht eingeschränkt und können neben Bildern,
Texten oder Filmen auch andere Daten enthalten. [CDB-14a]
In CouchDB wird anders als in MongoDB keine Abfragesprache für den
Datenzugriff bereitgestellt. Zugriffe auf die Daten erfolgen REST-basiert, d.h. über
die HTTP-Aufrufe GET, PUT, POST und DELETE. [RW-12]
Zur Aggregation und Darstellung der Dokumente verfügt CouchDB über ein
integriertes View-Modell. Views werden dynamisch erzeugt und beeinflussen die
zugrundeliegenden Dokumente nicht. Es können beliebig viele unterschiedliche
Views der gleichen Daten angelegt werden. Sie werden mittels JavaScript und
44
Map Reduce erstellt und in sogenannten Design Documents gespeichert. Design
Documents können beliebig viele Views enthalten und werden als „normale“
Dokumente in CouchDB gespeichert. Neben Views können auch andere
anwendungsbezogene Funktionen, z.B. zur Validierung, in Design Documents
gespeichert werden. [EFH-11]
Bei Abfrage einer View werden die Dokumente in alphanumerischer Sortierung
bezüglich ihrer abgefragten Keys ausgegeben. Daher ist es wichtig beim Erstellen
von Views die Keys so auszuwählen, dass ihre Sortierung für den jeweiligen
Abfragezweck sinnvoll ist. [RW-12]
Diese Sortierung ist gleichzeitig die Art von Indexierung die CouchDB bietet. In
den meisten Systemen werden die Ergebnisse von Map-Reduce-Aufrufen nach
Beenden der Abfrage verworfen. Daher müssen diese Aufrufe bei Bedarf jedes
Mal neu ausgeführt werden. CouchDB verhält sich anders und speichert die
Zwischenergebnisse der Mapper- und Reduce-Funktionen. Wird ein Dokument
geändert, wodurch diese Zwischenergebnisse im Normalfall nicht mehr korrekt
sind, führt CouchDB inkrementell die Mapper- und Reduce-Funktionen aus, um
die gespeicherten Werte zu korrigieren. CouchDB muss also nicht jedes mal von
Neuem die komplette Map Reduce-Funktion ausführen und kann diese so als
Indexierungsmechanismus
verwenden.
[RW-12]
In
CouchDB
erfolgt
die
Indexierung also automatisch bei Änderungen der Daten. Wird eine View das erste
Mal aufgerufen, wird auf diesen Daten ein B-Baum-Index aufgebaut und
nachfolgende Abfragen auf dem Baum ausgeführt. [Tiw-11]
CouchDB bietet mit der Changes-API ein Interface, mit dem die Datenbank in
Hinblick auf Veränderungen überwacht werden kann. So kann auf Änderungen der
Daten direkt, automatisch reagiert werden. Des Weiteren ist es auch möglich
Veränderungen zu filtern und so individuell auf unterschiedliche Updates
einzugehen [RW-12].
Da wie oben erwähnt Design Documents wie alle anderen Dokumente behandelt
werden und daher auch repliziert werden können, ist es in CouchDB möglich
45
vollständige Datenbankanwendungen einschließlich Anwendungsdesign, Logik
und Daten über Replikation auszutauschen. Solche Anwendungen bezeichnet
man als CouchApps. Ein Beispiel für CouchApps ist das von CouchDB zur
Verfügung gestellte Web-Interface Futon. Mit ihm kann die Datenbank auf
einfachem Weg verwaltet werden. [EFH-11]
Wie bereits erläutert, ist CouchDB ein schemaloses Datenbanksystem. Es
ermöglicht also jederzeit das Schema mittels Einfügen neuer Daten an aktuelle
Anforderungen anzupassen, ohne dass vorab eine Schemadefinition erforderlich
ist. Lediglich die Datenbank, in die Dokumente eingefügt werden sollen, muss vor
dem Einfügen definiert werden. Das Erzeugen einer neuen Datenbank kann aber
durchaus erst zur Laufzeit erfolgen.
Ebenso wie auch schon der Großteil der im Vorfeld analysierten Datenbanken
stellt CouchDB kein gesondertes Schema-Management zur Verfügung.
Auch hier ist es wieder von der konkreten Modellierung abhängig, ob Entity-Typen
mit den verfügbaren Schemainformationen beschrieben werden können. Da es
anders als bei MongoDB keine Collections gibt, können verschiedene Entity-Typen
entweder durch unterschiedliche Datenbanken repräsentiert werden oder auf
andere Art und Weise wie z.B.mit Hilfe eines Document-Type-Feldes innerhalb des
Dokumentes.
CouchDB verwaltet Metadaten zu Datenbanken und Dokumenten (auch Design
Documents).
Hierzu
zählen
z.B.
Dokument-ID,
Dokument-Revision
oder
Dokument-Revisionshistorie. Allerdings werden keine Informationen zu der
Struktur der Dokumente gespeichert. [CDB-14b, CDB-13a] Aus diesem Grund ist
es in CouchDB nicht möglich die Struktur der Entity-Typen zu beschreiben.
Dadurch können logischerweise auch keine Einschränkungen der Properties im
Schema modelliert werden.
46
Wie schon MongoDB reserviert auch CouchDB das _id-Feld für den Primary Key.
Daher ist es theoretisch nicht zwingend notwendig den Primary Key explizit im
Schema zu kennzeichnen. [CDB-13a]
Beziehungen können in CouchDB nicht im Schema definiert werden. Es wird kein
standardisiertes Format zur Kennzeichnung von Beziehungen zur Verfügung
gestellt. Je nach Kardinalität der Beziehung existieren verschiedene mögliche
Varianten der konkreten Modellierung. Es werden aber keine Metadaten zu diesen
Beziehungen verwaltet. [CDB-11a]
Ein
CouchDB-Schema
beinhaltet
also
Metadaten
zu
Datenbanken
und
Dokumenten. Dies ist allerdings nicht ausreichend, um Entity-Typen inklusive ihrer
Struktur, sowie Beziehungen zwischen Entity-Typen bzw. ihren Properties zu
modellieren.
CouchDB bietet die Möglichkeit die gespeicherten Schema-Informationen zu
extrahieren. Es werden hierfür verschiedene vordefinierte Views zur Verfügung
gestellt, die mittels GET-Call aufgerufen werden können. [CDB-14c] Tabelle 5 gibt
einen Überblick über die verschiedenen Aufrufe und ihre Funktion. Mit ihnen
können
z.B.
alle
Dokumente
einer
Datenbank
aufgelistet
werden
und
Metainformationen zu Datenbanken oder Dokumenten abgefragt werden.
47
GET-Call
Funktion
GET
/database/_all_docs
Auflisten aller Dokumente einer Datenbank
GET
/database/_all_dbs
Auflisten aller Datenbanken eines Servers
Metainformationen einer Datenbank, z.B. Anzahl
GET /database
der Dokumente, gelöschter Dokumente und
Updates dieser Datenbank
Metainformationen
GET /database/docID
eines
Dokumentes,
z.B.
aktuelle Revisionsnummer und Revisionshistorie,
aber keine Infos zu enthaltenen Feldern
GET
/database/_design/
designdoc
GET
/database/_design/
designdoc/_info
Abfrage des Inhaltes des spezifizierten
Design Documents
Weitere Infos zum Design Document inklusive
Indexinformationen
Tabelle 5: Überblick der von CouchDB zur Verfügung gestellten GET-Calls zur Abfrage
der Schemainformationen, [CDB-14d, CDB-14e, CDB-14f, CDB-14g, CDB-14h]
Somit ist es zwar möglich die von CouchDB gespeicherten Schema-Informationen
aus einer gefüllten Datenbank zu extrahieren, aber für eine annähernd
vollständige Schema-Beschreibung reichen die verfügbaren Metainformationen
nicht aus.
Wie auch schon zuvor bei anderen analysierten NoSQL-Datenbanken ist die
Unterstützung der Schema-Evolution auch bei CouchDB abhängig von der
konkreten Modellierung.
Die Möglichkeit Datenbanken und Dokumente hinzuzufügen und zu löschen wird
aber in jedem Fall von CouchDB bereitgestellt. Mit Hilfe von PUT /database
bzw. DELETE /database
kann eine neue Datenbank angelegt bzw. eine
existierende Datenbank gelöscht werden. [CDB-14f] Das Umbenennen einer
Datenbank wird nicht explizit von CouchDB unterstützt. Allerdings ist hierfür das
48
Umbenennen der Dateien, in denen die Datenbank gespeichert ist, ausreichend
und somit leicht umsetzbar. [Sta-12]
Analog hierzu werden neue Dokumente und Design Documents mittels
PUT /database/docID bzw.
PUT /database/_design/designdoc in
der Datenbank gespeichert. Existiert das durch Dokument-ID bzw. Design
Document-Namen spezifizierte Dokument bereits, wird eine neue Revision
gespeichert. Gleichermaßen werden (Design) Dokumente durch einen DELETEAufruf gelöscht. [CDB-14g, CDB-14h]
Weiterhin
gibt
es
zusätzlich
die
Möglichkeit
auch
mit
dem
Aufruf
POST /database ein neues Dokument zu speichern. In diesem Fall muss die
Dokument-ID nicht zwingend angegeben werden. Falls keine ID beim Aufruf
mitgeliefert wird, generiert CouchDB eine Dokument-ID. Existiert eine als
Parameter mitgelieferte ID bereits, wird nicht, wie oben bei der Nutzung von PUT,
eine neue Revision angelegt, sondern es kommt zu einer Fehlermeldung. [CDB14f]
Da CouchDB keine Schema-Informationen zur Struktur der Entity-Typen verwalten
kann, gibt es auch keine Möglichkeit die Properties eines Entity-Typs zu
verändern.
CouchDB validiert zumindest gegen die wenigen Schema-Informationen, die zur
Verfügung stehen. Existiert eine Datenbank nicht, wird bei dem Versuch auf sie
zuzugreifen eine Fehlermeldung geliefert. Gleiches gilt für Dokumente. [CDB-14f,
CDB-14g]
Des Weiteren unterstützt CouchDB sog. Validation Functions. Enthält ein Design
Document
eine
Funktion
namens
validate_doc_update,
wird
diese
automatisch vor dem Speichern eines Dokumentes aufgerufen. Jedes Design
Document kann maximal eine Validation Function enthalten. Soll ein Dokument
gespeichert werden, werden die Validation Functions aller Design Documents der
Datenbank nacheinander, in nicht genau spezifizierter Reihenfolge aufgerufen.
49
Sollte eine der Validation Functions eine Fehlermeldung ausgeben, schlägt der
Speichervorgang fehl. [CDB-14i]
Mit den Validation Functions erleichtert CouchDB die Validierung gegen ein
konkretes
Schema
und
automatisiert
diese
teilweise.
Die
eigentliche
Validierungslogik muss allerdings vom Anwender geschrieben werden. CouchDB
kann nur die Ausführung der Funktionen bieten.
Mehrere (parallel gültige) Schema-Versionen werden von CouchDB nicht
unterstützt. Trotz
gespeicherter
Revisionshistorie
und
Changes-API
kann
CouchDB keine built-in Unterstützung mehrerer Schema-Versionen liefern. Die
Revisionshistorie wird nicht dauerhaft gespeichert und kann daher nicht verlässlich
genutzt werden. [CDB-11b] Nichts desto trotz bietet CouchDB mit diesen zwei
Mitteln eine Unterstützung auf die bei der Entwicklung einer eigenen Revisionsoder Schema-Verwaltung aufgebaut werden kann.
Da die einzigen Schema-Informationen, die von CouchDB verwaltet werden,
Metadaten bezüglich Datenbanken und Dokumenten sind, ist eine Datenmigration
nicht erforderlich. Die einzigen Schema-Änderungen, für die eine Migration in
Frage käme, sind das Einfügen und Löschen einer Datenbank bzw. eines
Dokumentes. Beim Einfügen einer neuen Datenbank existieren noch keine Daten,
die migriert werden müssten. Wird ein neues Dokument eingefügt gilt das Gleiche.
Falls das einzufügende Dokument bereits existiert und eine neue Revision
gespeichert wird, entsteht auch in diesem Fall kein Bedarf die alten Daten zu
migrieren, denn die neue Dokumenten-Revision enthält bereits die aktualisierten
Daten. Dass beim Löschen eines Dokumentes keine Daten zu migrieren sind, ist
selbsterklärend. Gleiches gilt für das Löschen einer Datenbank, bei dem auch die
Daten gelöscht werden und somit keine Datenmigration erfolgen muss.
Zusammenfassend lässt sich sagen, dass CouchDB, wie die Mehrheit der zuvor
analysierten NoSQL-Datenbanken, nur wenig Unterstützung des SchemaManagements bietet. Auch CouchDB scheitert schon an der Anforderung EntityTypen inklusive ihrer Struktur beschreiben zu können und speichert nur Metadaten
50
zu Datenbanken und Dokumenten. Ob dies wenigstens zur Beschreibung
verschiedener Entity-Typen (ohne ihre Struktur) ausreichend ist, ist abhängig von
der konkreten Modellierung. Die verfügbaren Metadaten können allerdings auch
aus einer bereits gefüllten Datenbank extrahiert werden. Weiterhin wird deren
Evolution teilweise von CouchDB unterstützt. Die nachfolgende Tabelle 6 gibt
einen zusammenfassenden Überblick der von CouchDB erfüllten Anforderungen
eines Schema-Managements.
51
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
X
Delete Entity-Type
X
X
X
X
X
X
X
X
X
Rename Entity-Type
X
Update Entity-Type
X
X
X
X
X
X
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
Kennzeichnung als Primary Key
Beziehungen
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
X
Mehrere Schema-Versionen
X
X
X
X
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
Metadaten
zu
Datenbanken
und
Dokumenten
nicht notwendig, _id-Feld reserviert
Nur Auslesen von Metadaten
Einfügen neuer Datenbank
Löschen einer Datenbank
Durch Umbenennen der DatenbankDatei(en) realisierbar
Keine Modellierung von Properties
gegen Datenbank & Dokument-ID,
Validation Functions möglich
Tabelle 6: Überblick der von CouchDB erfüllten Anforderungen an ein SchemaManagement
52
3.2.7
Couchbase
Eine weitere Document NoSQL-Datenbank ist Couchbase. Couchbase entstand
im Februar 2011 durch den Zusammenschluss von CouchDB und Membase (eine
Key/Value NoSQL-Datenbank) mit dem Ziel die Vorteile beider Systeme zu
vereinen [Cou-13a]. Hinsichtlich Schemarestriktionen verhält sich Couchbase
ebenso offen wie CouchDB [Cou-13b].
Daten in Couchbase werden als Key/Value-Paare gespeichert. Keys identifizieren
eine Entity eindeutig. Values sind üblicherweise JSON-Dokumente, können aber
auch ein ByteStream oder andere Arten serialisierbarer Objekte sein. Also werden
in Couchbase im Normalfall Key/Document-Paare gespeichert. [Cou-13c]
Wie in CouchDB gibt es in Couchbase keine in-place-Updates, sondern für jedes
Dokument wird zusätzlich eine Sequenznummer verwaltet (bei CouchDB die
Revisionsnummer). Bei Änderungen eines Dokumentes wird ein neues Dokument
mit
inkrementierter
Sequenznummer
gespeichert.
Ältere
Versionen
von
Dokumenten dienen, wie auch in CouchDB, jedoch nur der Konflikterkennung bzw.
-lösung und werden nicht dauerhaft gesichert. [Cou-13d]
Zur Gruppierung von Dokumenten existieren in Couchbase sogenannte Buckets.
Sie sind das Äquivalent zur Datenbank in relationalen Systemen. [Cou-13c] Sie
definieren einen Namespace, sodass in verschiedenen Buckets der gleiche
Dokument-Key für unterschiedliche Dokumente verwendet werden kann. [Cou13e]
Couchbase stellt zwei verschiedenen Arten von Daten-Buckets zur Verfügung.
Eine Möglichkeit sind Couchbase Buckets, mit denen Daten persistent auf der
Festplatte gespeichert werden. Dokumente in Couchbase Buckets können bis zu
20 MB groß sein und repliziert werden. [Cou-13b]
Im Gegensatz dazu liegt die maximale Größe von Dokumenten in einem
Memcached Bucket, der zweite Typ von Buckets in Couchbase, bei nur 1 MB.
Daten in diesen Buckets werden nur im RAM gehalten und nicht persistent auf der
53
Festplatte gesichert. Außerdem können diese Dokumente nicht repliziert werden.
Je nach Anforderungen der Anwendung ist es möglich verschiedene Arten von
Buckets miteinander zu kombinieren. [Cou-13b]
Für den Datenzugriff existieren in Couchbase zum einen das MemcachedProtokoll und zum anderen die aus CouchDB bekannten Views. Für die
Basiszugriffe Create, Update und Delete wird das Memcached-Protokoll
eingesetzt. Es stellt Methoden zum kompletten Update von Dokumenten sowie der
Ausführung von simplen Operationen, wie zum Beispiel dem Einfügen neuer
Informationen in ein Dokument oder der Inkrementierung/ Dekrementierung von
Integer-Werten, zur Verfügung. [Cou-13b]
Zur Datenabfrage kann, falls der Dokument-Key bekannt ist, ebenfalls das
Memcached-Protokoll genutzt werden. Um Keys und Values oder nur Values in die
Abfrage einzubeziehen können Views eingesetzt werden. So können mit Views
beispielsweise auch Abfragen ausgeführt werden, wenn der Key unbekannt ist.
[Cou-13b]
Auch in Couchbase wird durch die Nutzung von Views automatisch ein Index auf
den Daten erstellt. Die Index-Generierung basiert auf den Feldern des JSONDokumentes und wird daher nur für JSON-Dokumente erstellt. Sollten Values in
einem anderem Format als JSON in Couchbase gespeichert worden sein, werden
diese bei der Index-Generierung ignoriert. Genauso wie in CouchDB werden
Views
in
Design
Documents
gespeichert
und
Indexe
automatisch
bei
Dokumentänderungen aktualisiert. Jedes Design Document ist einem bestimmten
Bucket zugeordnet und die darin enthaltenen Views können nur auf Daten
innerhalb dieses Buckets zugreifen. [Cou-13f]
Die von CouchDB bereitgestellte Möglichkeit Anhänge zu Dokumenten zu
speichern existiert in Couchbase nicht. Anhänge können nur als neue separate
Dokumente in der Datenbank gespeichert werden und sich daraus ergebende
Beziehungen müssen in der Anwendung verwaltet werden. [Cou-13b]
54
Daher werden auch CouchApps nicht von Couchbase unterstützt. Daraus
resultiert das Fehlen von Futon in Couchbase. Stattdessen wird eine Web
Administration Console zur Verfügung gestellt, mit der u.a. Buckets, Views und
Dokumente verwaltet und geändert werden können. [Cou-13b, Cou-13g]
Wie auch CouchDB ist Couchbase ein schemaloses System, in dem keine
Vorabdefinition
eines
Schemas
notwendig
ist.
Neu
einzufügende
Daten
unterliegen somit keinen Schema-Restriktionen. Hierdurch ist eine Änderung des
Schemas zu jedem Zeitpunkt ohne Aufwand möglich.
Aus diesem Grund stellt auch Couchbase kein explizites Schema-Management
zur Verfügung. Ebenso ist es wie bei fast allen anderen im Vorfeld analysierten
NoSQL-Datenbanken von der konkreten Modellierung abhängig, ob Entity-Typen
verwaltet werden können. Von Couchbase werden verschiedene Metadaten
gespeichert. Hierzu zählen u.a. Dokument-Metadaten wie ID, Revision und ValueType (da neben JSON auch andere Value-Formate möglich sind), die in einem
separaten JSON-Objekt gespeichert werden. [Cou-13f] Die verschiedenen EntityTypen können beispielsweise durch unterschiedliche Buckets repräsentiert
werden, aber auch andere Varianten wie z.B. die Kennzeichnung des Entity-Typs
durch ein Type-Feld innerhalb des JSON-Dokumentes sind denkbar.
Metadaten hinsichtlich der Felder von Dokumenten werden nicht verwaltet [Cou13f]. Daher ist es nicht möglich die Struktur von Entity-Typen sowie
Einschränkungen bezüglich der Properties zu modellieren.
Ähnlich wie bei MongoDB und CouchDB wird das id-Feld für den Primary Key
reserviert, daher ist es auch hier theoretisch nicht notwendig ihn explizit im
Schema zu definieren. [Cou-13f]
Referenzen zwischen Dokumenten können auf verschiedene Arten realisiert
werden. Allen gemein ist allerdings, dass die Verwaltung, d.h. sowohl das Anlegen
wie auch Auflösen, der Referenzen auf Anwendungsebene erfolgen muss. Mit
55
anderen Worten bietet Couchbase keine Unterstützung, um Referenzen zu
modellieren und zu managen. [Cou-13h]
Um die gespeicherten Metadaten aus einer bestehenden Datenbank zu
extrahieren, müssen Views genutzt werden. Damit auf die Dokument-Metadaten
zugegriffen werden kann, muss eine zwei-parametrige Map-Methode genutzt
werden. Diese erhält als Parameter nicht nur das Dokument (doc als Parameter
für die Dokumenteninhalte), sondern ebenfalls die Metadaten (meta als Parameter
für die Dokument-Metadaten). Wird das Memcached-Protokoll für den Datenzugriff
genutzt,
werden
die
Metainformationen
nicht
gemeinsam
mit
den
Dokumentinhalten zurückgeliefert. [Cou-13f, Cou-13i]
Um Bucket-Metadaten auszulesen, genügt ähnlich wie bei CouchDB ein simpler
REST-Aufruf der Form GET /pools/default/buckets/bucketname. [Cou13e]
Also können bei Couchbase die verwalteten Metadaten aus einer bestehenden
Datenbank
extrahiert
werden.
Da
jedoch
keinerlei
Metadaten
zur
Dokumentstruktur gespeichert werden, ist es allerdings nicht möglich ein
komplettes Schema aus der Datenbank zu ermitteln.
Da bei Couchbase die Möglichkeit der Beschreibung von Entity-Typen von der
konkreten Modellierung abhängig ist, wird auch der Grad der Unterstützung der
Schema-Evolution, die von Couchbase geleistet wird, davon beeinflusst.
In jedem Fall gibt es die Möglichkeit neue Buckets und Dokumente anzulegen und
zu löschen. Das Hinzufügen eines Buckets erfolgt durch den Aufruf der POSTMethode, der als Parameter u.a. der Name und Typ des neuen Buckets
übergeben wird. Mittels Aufruf von POST können auch existierende Buckets
geändert
werden.
Analog
dazu
werden
Buckets
DELETE /pools/default/buckets/bucketname
mit
Hilfe
von
gelöscht. [Cou-13e] Ein
Umbenennen von Buckets wird nicht unterstützt. [Cou-13g]
56
Für den Basis-Zugriff auf Dokumente wird, wie oben erwähnt, das MemcachedProtokoll verwendet. Neue Dokumente können mittels set-Methode, z.B. des
CouchbaseClient der Java-API, gespeichert werden. Um ein Dokument zu
ändern, wird ebenfalls die set-Methode genutzt. Diese überschreibt das gesamte
Dokument, da in Couchbase keine Änderungen auf Feld-Ebene durchgeführt
werden können. Um ein Dokument zu löschen steht die delete-Methode, z.B. des
CouchbaseClient der Java-API, zur Verfügung. [Cou-13j, Cou-13k]
Da Couchbase keine Metadaten zur Dokumentstruktur verwaltet, ist auch keine
Unterstützung der Schema-Evolution hinsichtlich der Entity-Struktur möglich.
Die von Couchbase verwalteten Schemainformationen werden auch zur
Validierung eingesetzt. Bei dem Versuch auf nicht-existierende Buckets oder
Dokumente zuzugreifen liefert Couchbase eine Fehlermeldung. [Cou-13e, Cou13j] Eine tiefergehende Validierung z.B. gegen die Struktur der einzelnen EntityTypen wird aufgrund der fehlenden Metadaten nicht von Couchbase unterstützt.
Die in CouchDB genutzten Validation Functions werden von Couchbase nicht
angeboten. [Cou-13b] So obliegt die Validierung, abgesehen von den im
vorherigen Absatz erwähnten Ausnahmen, der Anwendung.
Wie auch von CouchDB, werden von Couchbase mehrere Schema-Versionen
nicht unterstützt. Es werden zwar Sequenznummern zu den Dokumenten
gespeichert, diese dienen aber lediglich der Konflikterkennung und -lösung und
können somit nicht zur Verwaltung mehrerer Schema-Versionen dienen. [Cou-13f]
Weiterhin besteht ein Couchbase-Schema nur aus Metadaten zu Buckets und
Dokumenten. Mehrere parallel gültige Schema-Versionen sind mit diesen
begrenzten Informationen nicht möglich.
Aus den verfügbaren Schema-Informationen ergeben sich auch die für eine
Datenmigration in Frage kommenden Schema-Änderungen. Hier müssen nur die
Fälle des Löschens und Ändern von Buckets und Dokumenten betrachtet werden.
Beim Löschen eines Buckets bzw. Dokumentes werden die darin gespeicherten
57
Daten ebenfalls gelöscht. Bei der Änderung eines Dokumentes werden die Daten
selbst geändert und das komplette Dokument überschrieben, wodurch eine
Datenmigration logischerweise unnötig ist. Da die Dokumente selbst keine
Informationen zu den Buckets beinhalten, ist es nicht erforderlich eine
Datenmigration durchzuführen, wenn Metadaten des Buckets geändert werden.
Alleine die Tatsache, dass im Fall des Löschens eines Buckets auch die darin
enthaltenen Daten gelöscht werden, kann nicht als (teilweise) Unterstützung der
Datenmigration gewertet werden.
In der nachfolgenden Tabelle 7 sind die Analyseergebnisse noch einmal
abschließend zusammengefasst. Es lässt sich sagen, dass auch Couchbase nur
wenig Möglichkeiten des Schema-Managements bietet. Es fehlt alleine schon ein
Mechanismus, um Entity-Typen mitsamt ihrer Struktur zu modellieren. Daher
können auch die weiteren Anforderungen an ein Schema-Management aus 3.1
nicht erfüllt werden.
58
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
Kennzeichnung als Primary Key
Beziehungen
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
Validierung
X
Mehrere Schema-Versionen
X
X
X
X
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
Metadaten
zu
Buckets
und
Dokumenten
nicht notwendig, id-Feld reserviert
Nur Auslesen von Metadaten
Einfügen neuer Buckets
Löschen von Buckets
Keine Modellierung von Properties
Gegen Existenz von Buckets &
Dokument-ID
Tabelle 7: Überblick der von Couchbase erfüllten Anforderungen an ein SchemaManagement
59
3.2.8
Gesamtüberblick NoSQL-Datenbanksysteme
Die in Tabelle 8 zusammengefassten Analyseergebnisse aller NoSQL-Systeme
zeigen, dass die analysierten Systeme nur eine rudimentäre Unterstützung des
Schema-Managements bieten können.
Von CouchDB und Couchbase kann sogar keine der Anforderungen wenigstens
annähernd erfüllt werden. Obwohl auch in diesen beiden Systemen einige
Metadaten verwaltet werden, fehlt es jedoch schon an einem geeigneten
Konstrukt, um zumindest verschiedene Entity-Typen definieren zu können.
Im Vergleich dazu können MongoDB und HBase immerhin eine teilweise
Unterstützung
anbieten.
In
beiden
Systemen
existieren
Möglichkeiten
verschiedene Entity-Typen zu definieren. Jedoch ist es nicht möglich deren
Struktur, also deren Properties, im Schema zu beschreiben.
Da in diesen beiden Systemen das Schema auf Entity-Typen ohne ihre Struktur
beschränkt ist, sind auch Schema-Extraktion und -Evolution auf die Entity-Typen
an sich begrenzt und werden daher nur mangelhaft unterstützt. Informationen zu
Properties sind den Systemen unbekannt und können daher nicht berücksichtigt
werden.
Als einziges der untersuchten Systeme kann MongoDB wenigstens eine teilweise
Unterstützung der Eager Datenmigration bieten. Dies betrifft das Einfügen,
Löschen sowie Umbenennen von Entity-Typen. Auch im Fall des Umbenennens
von Entity-Typen bildet MongoDB eine Ausnahme und bietet als einziges der
analysierten Systeme eine Unterstützung für diese Operation an.
Der
GAE
Datastore
kann
in
Verbindung
mit
dem
Python
SDK
die
Schemamodellierung fast vollständig realisieren. Auch Beziehungen können
definiert und automatisch dereferenziert werden. Lediglich Einschränkungen in der
Verfügbarkeit von Constraints beschränken die Schemamodellierung. Auch eine
Validierung
gegen
das
erstellte
Schema
wird
geleistet.
Gleichermaßen
umfangreich ist die Schemaextraktion. Es lässt sich mit den vom GAE Datastore
60
und dem Python SDK zur Verfügung stehenden Mitteln mit Ausnahme der
fehlenden Constraints ein komplettes Schema extrahieren.
Im Bereich der Schema-Evolution können GAE Datastore und Python SDK jedoch
nur eine mangelhafte Unterstützung bieten. Es werden lediglich Methoden zum
Hinzufügen von Properties angeboten. Das Hinzufügen von Entity-Typen ist zwar
möglich, muss jedoch auf Code-Basis erfolgen und kann daher nicht als wirkliche
Unterstützung von GAE Datastore angesehen werden.
Als einziges der untersuchten Systeme kann GAE Datastore eine teilweise
Realisierung mehrerer Schema-Versionen bieten. Mit Nutzung der ExpandoModel-Klasse können dynamic Properties zur Laufzeit definiert werden, so dass
theoretisch mehrere Schema-Versionen existieren, zu denen auch Metadaten
gespeichert werden. Explizit mehrere Schema-Versionen oder gar eine SchemaHistorie werden von GAE Datastore allerdings nicht verwaltet.
Auch ist zu sagen, dass sich die Erfüllung der Anforderungen größtenteils aus
dem genutzten Python SDK ergibt. Wird ein anderes SDK eingesetzt, können sich
die Analyseergebnisse verändern und weniger oder andere Anforderungen erfüllt
sein.
Cassandra kann als einziges der analysierten Systeme built-in eine relativ
umfassende Unterstützung der Schema-Modellierung anbieten. Es mangelt zwar
an Konstrukten, um Beziehungen darzustellen, jedoch sind diese in NoSQLSystemen aufgrund der großen Datenmengen ohnehin mit Vorsicht zu genießen.
Im Normalfall werden Referenzen im denormalisierten Datenmodell nicht
gebraucht und die Informationen innerhalb der Entities verschachtelt und oft auch
redundant gespeichert. Allerdings ist es abgesehen vom erforderlichen PrimaryKey-Constraint nicht möglich Einschränkungen von Properties zu modellieren.
Selbst Existenz- oder Einzigartigkeitsbedingungen werden nicht unterstützt. Um
eine ausreichende Schema-Modellierung zur Verfügung zu stellen, fehlen diese
Kriterien allerdings.
61
Im Gegensatz zum GAE Datastore kann Cassandra die Schemaevolution
weitreichender unterstützen. Von allen untersuchten Systemen bietet Cassandra
in diesem Punkt die meiste Unterstützung. Dennoch werden auch in diesem Fall
nur einige der Anforderungen erfüllt. So werden zwar das Hinzufügen und
Löschen von Entity-Typen und Properties unterstützt, aber weitergehende
Methoden für das Umbenennen von Entity-Typen oder Properties, sowie das
Kopieren oder Verschieben von Properties kann auch Cassandra nicht zur
Verfügung stellen.
Abschließend lässt sich sagen, dass von den analysierten, momentan wichtigsten,
NoSQL-Systemen bislang nur eine unzureichende Unterstützung des SchemaManagements angeboten wird.
62
Feature
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
Kennzeichnung als Primary Key
Beziehungen
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
Mehrere Schema-Versionen
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
GAE
Cassan
Mongo Couch Couch
HBase
Datadra
DB
DB
base
store
(✓) (✓) ✓
(✓) ✓
✓
X
✓
✓
X (✓) (✓)
X
✓
✓
X
X
✓
(✓) (✓) ✓
(✓) (✓) (✓)
(✓) ✓ (✓)
X
(✓) ✓
X
X
X
X (✓) X
X
✓
✓
X
X
✓
X
X
X
X
X
X
X
X
X
(✓)
X
X
X
X
✓
X
X
X
X
(✓)
(✓)
X
X
X
X
(✓)
(✓)
(✓)
(✓)
(✓)
X
X
X
X
X
X
X
✓
(✓) X
X (✓)
X (✓)
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
Tabelle 8: Gesamtüberblick der von den analysierten NoSQL-Systemen erfüllten
Anforderungen an ein Schema-Management
63
3.3
Aktuelle Entwicklungen im Bereich des SchemaManagements
Es existieren eine Vielzahl verschiedener, meist proprietärer Ansätze, um das
Schema-Management in NoSQL-Datenbanksystemen besser zu unterstützen.
Dies reicht vom umfangreichen Framework über Object-To-NoSQL-Mapper bis hin
zu spezifischen Libraries. Nachfolgend werden die vielversprechendsten Ansätze
hinsichtlich ihrer Unterstützung der in 3.1 aufgestellten Anforderungen an ein
Schema-Management untersucht.
3.3.1
KijiSchema
KijiSchema ist eine Komponente des KijiProjects, ein modulares Open Source
Framework, das auf HBase aufbaut. KijiSchema ist die Architekturschicht, die
Serialisierung
der
Daten,
Schema-Design
und
-Evolution
sowie
das
Metadatenmanagement bereitstellt. Für den Datenzugriff stehen eine Java API
oder Kommandozeilen-Tools zur Verfügung. [Kij-14a, Kij-14b]
Das von KijiSchema genutzte Datenmodell ist Entity-zentriert und erweitert das
von HBase eingesetzte Speichermodell. Die Daten werden in sogenannten KijiTabellen abgelegt. Jede Kiji-Tabelle wird auf eine physische HBase-Tabelle
abgebildet. [Kij-14c, Kij-14d]
Wie auch HBase-Tabellen speichern Kiji-Tabellen Daten in Rows, von denen jede
beliebig viele Columns enthalten kann. Eine Zelle wird durch Row-ID und ColumnNamen identifiziert und die Daten mittels Timestamp versioniert. Da KijiSchema
auf HBase basiert, ist es ebenfalls ein Schema-flexibles System und
unterschiedliche Rows einer Tabelle müssen nicht notwendigerweise die gleichen
Columns besitzen. [Kij-14c]
Ebenso wie in HBase werden auch in KijiSchema Columns in Column Families
gruppiert. Column-Families selbst werden in sogenannten Locality Groups
gruppiert. Mit Hilfe der Locality Groups wird sichergestellt, dass Column Families,
64
die logisch miteinander in Verbindung stehen, physisch zusammen bzw. möglichst
nah gespeichert werden. Locality Groups sind also das Äquivalent zu den Column
Families in HBase. Kiji Column Families ermöglichen es, eine logische
Gruppierung von Columns, unabhängig von der physischen Speicherung,
vorzunehmen. [Kij-14c]
Ein Row-Key besteht in KijiSchema aus einer oder mehreren Columns, die vom
Datentyp String, Int oder Long sein können. Es existiert die Möglichkeit von
Compound Keys, die ähnlich wie in Cassandra zum Aufbau einer zusätzlichen
Hierarchie genutzt werden können. Um bei der Speicherung der Daten in HBaseTabellen fortlaufende Row-Keys zu vermeiden, da diese zu Hot-Spots führen
würden, wird dem Key ein auf der ersten Komponente des Row-Keys basierender
Hash-Wert vorangestellt. Es ist allerdings möglich, die Nutzung beliebig vieler
Row-Key-Komponenten für die Berechnung des Hash-Wertes zu konfigurieren.
Alle Komponenten des Row-Keys, die nicht im Hash-Wert enthalten sind, werden
benachbart gespeichert und bestimmen dadurch die Sortierreihenfolge der
gespeicherten Rows. [Kij-14e, Kij-14f]
Die Daten einer Kiji-Zelle werden zwecks Speicherung, unter Verwendung von
Apache Avro, in ein Byte-Array serialisiert. [Kij-14e] Apache Avro ist ein
Framework zur Serialisierung von Daten, das auf der Nutzung von Schemata
basiert. Avro Schemata werden mittels JSON definiert und bestehen aus primitiven
Typen wie null, boolean oder int und komplexen Typen beispielsweise record,
array oder map. Werden Daten gespeichert, wird ihr Schema zusammen mit den
Daten abgelegt, so dass die Daten zu einem späteren Zeitpunkt von jedem
beliebigen Programm deserialisiert und verarbeitet werden können. [Avr-14a]
65
Eine Avro-Schema vom Typ „record“ kann wie folgt aussehen:
{
„type“: „record,
„name“: „User“,
„fields“: [
{„name“: „name“, „type“: „string“},
{„name“: „favorite_number“, „type“: „int“},
{„name“: „favorite_color“, „type“: [„string“, „null“]}
]
}
Abbildung 5: Beispiel eines Avro-Schemas für eine User-Entity
Obiges Beispiel zeigt ein Schema für eine User-Entity. Die Properties des EntityTyps werden über ein Array von Objekten definiert. Jedes Objekt definiert Namen
und Typ des jeweiligen Feldes. In obigem Beispiel werden für den Entity-Typ
„User“ die Properties name mit dem Datentyp string, favorite_number mit dem
Datentyp int und favorite_color, als optionales Feld vom Typ string oder null,
definiert. [Avr-14b, Avr-14c]
Da in Avro der Begriff Schema eine definierte Bedeutung hat, verwendet
KijiSchema diese Bezeichnung für ein Avro-Schema. Mit jeder Zelle einer KijiTabelle sind ein oder mehrere Avro-Schemata assoziiert. Die Bezeichnung für die
gespeicherten Metadaten zu einer Tabellen-Struktur lautet Layout. [Kij-14g, Kij14c]
Zu jeder Kiji-Tabelle wird ein Layout verwaltet. Es kann mittels SQL-ähnlicher, von
KijiSchema zur Verfügung gestellter, DDL (Data Definition Language) oder einer
JSON-Layout-Beschreibung definiert werden. [Kij-14e]
Im Tabellen-Layout werden Informationen zu Tabelle, Locality Group, Column
Families und Columns gespeichert. Weiterhin wird im Layout für jede Column ein
sogenanntes minimales Avro Reader-Schema spezifiziert. [Kij-14e]
66
Das Avro Writer-Schema, welches für eine spezifische Schreiboperation genutzt
wird, wird gemeinsam mit den Daten gespeichert, um bei darauffolgenden
Lesezugriffen eine exakte Deserialisierung gewährleisten zu können. [Kij-14e]
Da es ineffizient wäre, die komplette Definition des Writer-Schemas in jeder Zelle
zu speichern, bietet KijiSchema drei verschieden Varianten an. Das WriterSchema kann entweder über einen MD5-Hash oder eine generierte, numerische,
eindeutige ID identifiziert werden. In den Zellen wird jeweils nur der Hash-Wert
oder die ID gespeichert. Das komplette Writer-Schema wird in der Kiji-Tabelle mit
dem Hash-Wert oder der ID als Key abgelegt. Als dritte Variante gibt es die
Möglichkeit das Writer-Schema überhaupt nicht in der Zelle zu speichern.
Stattdessen wird implizit angenommen, dass das Writer-Schema mit dem im
Tabellen-Layout definierten Reader-Schema übereinstimmt. Unabhängig davon
welche dieser drei Varianten eingesetzt wird, muss das Writer-Schema mit dem im
Layout spezifizierten Reader-Schema der Zelle kompatibel sein. [Kij-14e]
Zur weiteren Unterstützung der Schema-Flexibilität existieren in KijiSchema zwei
verschiedene Arten von Column Families, die sich in ihrer Art der gespeicherten
Metadaten unterscheiden. Zum einen gibt es Group-Type Families. Sie definieren,
ähnlich wie in einem Cassandra-Schema, eine feste Menge von Columns, die die
Rows enthalten können, aber nicht müssen. Zusätzlich definierte Columns dürfen
in Rows dieser Column Family nicht enthalten sein. Group-Type Families
speichern Avro-Schemata zu den einzelnen Columns. Zum anderen gibt es MapType Families, die nicht explizit bestimmte Columns definieren. Sie verwalten ein
einziges Avro-Schema für alle ihre Columns. [Kij-14e]
Jeder Prozess der auf die Daten zugreift kann eigene, bevorzugte Reader- und
Writer-Schemata mit einer Column assoziieren. Somit unterstützt KijiSchema
mehrere, versionierte, parallel gültige Schemata. [Kij-14e, Kij-14h]
Seit Version 1.3.0 stellt KijiSchema ein Konzept zur sicheren Schema-Evolution
des Table-Layouts zur Verfügung. Eine Zelle erlaubt beliebig viele assoziierte
Schemata, solange diese miteinander kompatibel sind. Um einer Zelle ein neues
67
Schema zuzuweisen, muss dieses mit den bis zu diesem Zeitpunkt bereits
genutzten Schemata kompatibel sein. Hierdurch wird sichergestellt, dass Daten,
die mit einem älteren Writer-Schema gespeichert wurden, von neueren Versionen
des Reader-Schemas weiterhin gelesen werden können, sowie dass Daten, die
mittels neuerer Writer-Schema-Versionen geschrieben werden auch weiterhin von
Anwendungen gelesen werden können, die ältere Reader-Schemata verwenden.
Jede Column verwaltet hierzu u.a. Listen aktiver Read- bzw. Write-Schemata,
sowie aller, nicht notwendigerweise noch aktiven, aber im Vorfeld genutzten WriteSchemata. Eine Datenmigration ist durch diese Kompatibilitätsbedingung nicht
erforderlich. [Kij-14e]
Die oben beschriebene Variante der Schema-Evolutions-Validierung ist nicht die
einzige Möglichkeit. KijiSchema unterstützt verschiedene Validierungsmodi. Der
Modus kann bei der Erzeugung der Tabelle konfiguriert oder im späteren Verlauf
geändert werden. Er bestimmt welche Reader- und Writer-Schemata mit einer
Column assoziiert werden können.
Es gibt zum einen die Variante NONE, bei der keine Validierung der SchemaÄnderung stattfindet. Bei Schreiboperationen wird nicht überprüft, ob das
eingesetzte Writer-Schema zur Menge der aktiven Writer-Schemata einer Column
gehört. Weiterhin gibt es den Modus LEGACY. Hier werden primitive Datentypen
zur Schreibzeit validiert, inkompatible Schema-Evolutionen sind jedoch erlaubt.
Die dritte Möglichkeit ist DEVELOPER, die Default-Konfiguration. Bei LayoutÄnderungen
wird
die
Kompatibilität
von
Reader-
und
Writer-Schemata
sichergestellt. Es ist jedem Prozess möglich zur Laufzeit neue, kompatible WriterSchemata hinzuzufügen. Die letzte, verfügbare Variante ist STRICT. Ebenso wie
mit der Konfiguration DEVELOPER erfolgt eine Validierung von Layoutänderungen
und die Kompatibilität wird sichergestellt. Allerdings ist es hier nur möglich neue,
kompatible Writer-Schema explizit mittels KijiShell hinzuzufügen und nicht wie bei
DEVELOPER von jedem Prozess zur Laufzeit möglich. Bei Änderungen des
Validierungsmodus gilt diese Änderung nur für im Anschluss daran eingefügte
Columns. Bereits existierende Columns behalten ihre Validierungskonfiguration
bei. [Kij-14f]
68
Weiterhin ist es in KijiSchema möglich einer Column ein Default-Reader-Schema
zuzuweisen, welches von Anwendungen, die kein eigenes Reader-Schema
bevorzugen, genutzt werden kann. KijiSchema validiert Änderungen am DefaultReader-Schema jedoch nicht. Die Kompatibilität muss also bei Updates des
Default-Reader-Schemas selbstständig sichergestellt werden und eine ggf.
erforderliche Datenmigration durchgeführt werden. [Kij-14f]
Da KijiSchema die Komponente des KijiProjects ist, die für Schema-Management
verantwortlich ist, ist logischerweise eine Beschreibung von Entity-Typen und ihrer
Struktur
realisierbar.
Die
verschiedenen
Entity-Typen
werden
mittels
unterschiedlicher Kiji-Tabellen repräsentiert. Unter Einsatz von Group-Type
Column Families kann die Struktur der Entities als Columns modelliert werden.
Zusätzlich werden Reader- und Writer-Schema definiert. Mit diesen Schemata
wird der Datentyp der Columns festgelegt. [Kij-14e] Eine Existenzbedingung für
Properties kann definiert werden, indem für die jeweiligen Properties im AvroSchema „null“ nicht als möglicher Datentyp angegeben wird. [Avr-14b, Avr-14c]
Eine weitere Einschränkung des Wertebereichs oder die Modellierung von
Einzigartigkeitsbedingungen ist allerdings nicht möglich.
Die Kennzeichnung von Properties als Primary Key wird von KijiSchema
unterstützt. Es gibt auch die Möglichkeit Compound Keys zu definieren, die
gleichzeitig die Sortierreihenfolge der gespeicherten Daten bestimmen. Ein
Compound Key bildet die einzige Ausnahme, mit der Existenzbedingungen im
Tabellen-Layout gekennzeichnet werden können. Die erste Komponente des Keys
besitzt implizit die not-null-Eigenschaft. Weitere Komponenten des Keys können
ebenfalls als nicht optional definiert werden. Jedoch ist es nicht möglich, falls eine
Komponente des Keys als optional festgelegt ist (nullable), nachfolgenden KeyKomponenten eine Existenzbedingung zuzuweisen. [Kij-14f]
Der Primary Key wird bei der Tabellen-Erzeugung z.B. mittels CREATE TABLE t
ROW KEY FORMAT (lastname STRING, firstname STRING NOT NULL)
definiert. Eine spätere Änderung des Row-Key-Formats ist nicht möglich. [Kij-14f]
69
Eine Möglichkeit Beziehungen zwischen Entity-Typen bzw. ihren Properties
darzustellen wird nicht von KijiSchema bereitgestellt. Dies sollte allerdings im
Normalfall
durch
die
Nutzung
eines
denormalisierten,
entity-zentrierten
Datenmodells, bei dem innerhalb einer Row alle für diese Row relevanten Daten
gespeichert werden, auch nicht notwendig sein.
KijiSchema verwaltet Metadaten zu Tabellen, Locality Groups, Column Families
und Columns. Diese Metadaten können auch aus einer gefüllten Datenbank
extrahiert werden. So können mit dem DDL-Befehl SHOW
TABLES alle
verfügbaren Tabellen angezeigt werden. Das Layout einer Tabelle wird mit dem
Aufruf DESCRIBE tablename abgefragt. Es werden Metadaten zur Tabelle und
den enthaltenen Column Families, sowie deren Columns ausgegeben. Darüber
hinaus ist das Default-Reader-Schema sowie die Anzahl weiterer Schemata jeder
Column in der Ausgabe enthalten. [Kij-14f]
Um zusätzlich zum Tabellen-Layout auch Informationen zu den Locality Groups
abzurufen wird der Befehl DESCRIBE EXTENDED tablename genutzt. Um alle
aktiven Reader-Schemata einer Column auszulesen, kann der Befehl DESCRIBE
tablename COLUMN cf:column SHOW READER SCHEMAS genutzt werden.
Analog können mit den Optionen SHOW WRITER SCHEMAS und SHOW RECORDED
SCHEMAS die aktiven Writer-Schemata sowie alle bisher genutzten, nicht
notwendigerweise noch aktiven Writer-Schemata abgefragt werden. [Kij-14f]
Es gibt auch die Möglichkeit die Java-API zum Auslesen der Metadaten zu nutzen.
Mit der getLayout()-Methode des KijiTable-Interface kann das TabellenLayout abgefragt werden. Die Klasse KijiTableLayout stellt diverse Methoden
für den Zugriff auf die Metadaten zur Verfügung. Mit den Methoden
getLocalityGroups() und getFamilies() dieser Klasse können die
LocalityGroups bzw. Column Families der Tabelle abgefragt werden. Mit Hilfe der
Methode getColumnNames() der KijiTableLayout-Klasse
können alle
Columns der Tabelle ausgelesen werden und die zu einer bestimmten Column
gehörige Zellspezifikation kann mit Hilfe der Methode getCellSpec() der
gleichen Klasse ausgelesen werden. Eine Zell-Spezifikation (Klasse CellSpec)
70
ist ein Wrapper um das Avro-Schema, damit ein ständiges Re-Parsen des JSON
Avro-Schemas vermieden wird. [Kij-14i]
Auch für die Schema-Evolution bietet KijiSchema einige Unterstützung. Die
Durchführung ist mittels KijiSchema-DDL oder Java API möglich. Es können,
abgesehen vom Umbenennen eines Entity-Typs und dem Verschieben/ Kopieren
von Properties, alle Evolutions-Operationen realisiert werden. Die nachfolgende
Tabelle 9 gibt einen Überblick über die zur Verfügung gestellten DDL-Befehle.
Nahezu alle Table-Properties können auch im späteren Verlauf geändert werden.
Einzige Ausnahme sind Tabellenname und Row-Key-Format. Ein Umbenennen
einer Tabelle ist also nicht möglich. Außerdem ist zu beachten, dass beim Löschen
einer Tabelle die darin enthaltenen Daten ebenfalls gelöscht werden. [Kij-14f]
Wird bei der Definition eines neuen Avro-Schemas nicht spezifiziert, ob ein
Reader- oder Writer-Schema hinzugefügt werden soll, wird das Schema in beide
Aktiv-Listen
der
Column
aufgenommen,
sofern
es,
entsprechend
des
konfigurierten Validierungs-Modus, als kompatibel identifiziert wurde. [Kij-14f]
Soll eine (ältere) Writer-Schema-Version nicht weiter verwendet werden, kann eine
Migration der Datenbank auf eine neuere Writer-Schema-Version realisiert
werden. Nachdem ein Update aller Anwendungen, die Daten in der Datenbank
speichern, auf die neue Writer-Schema-Version durchgeführt wurde, wird das
veraltete Writer-Schema aus der Liste der akzeptierten Writer-Schemata entfernt.
Existierende Daten, die mit diesem Schema gespeichert wurden, werden
allerdings nicht automatisch migriert. [Kij-14e]
71
DDL-Befehl
Funktion
CREATE TABLE tablename
WITH locality_group
Anlegen einer neuen Tabelle
DROP TABLE tablenname
Löschen einer Tabelle
ALTER TABLE tablename
ADD FAMILY cf TO
LOCALITY GROUP lg
Hinzufügen
einer
neuen
Column
Family
ALTER TABLE tablename
DROP FAMILY cf
Löschen einer Column Family
ALTER TABLE tablename
RENAME FAMILY cf AS newcf
Umbenennen einer Column Family
ALTER TABLE tablename
Hinzufügen
CREATE LOCALITY GROUP group
Group
ALTER TABLE tablename
DROP LOCALITY GROUP group
Löschen einer Locality Group
ALTER TABLE tablename
RENAME LOCALITY GROUP group
AS newgroup
Umbenennen einer Locality Group
ALTER TABLE tablename
ADD COLUMN cf:column
WITH SCHEMA schema
Hinzufügen einer neuen Column
ALTER TABLE tablename
DROP COLUMN cf:column
Löschen einer Column
ALTER TABLE tablename
RENAME COLUMN cf:column
AS cf:newcolumn
Umbenennen einer Column
ALTER TABLE tablename
ADD [ [DEFAULT] READER |
WRITER ] SCHEMA schema
FOR COLUMN cf:column
ALTER TABLE tablename
DROP WRITER SCHEMA schema
FOR COLUMN cf:column
Definition
einer
eines
neuen
neuen
Locality
Reader/
Writer Schemas
Entfernen eines Writer-Schemas aus
der Liste akzeptierter Schemata
Tabelle 9: Überblick der von KijiSchema zur Verfügung gestellten DDL-Befehle zur
Schema-Evolution, [Kij-14e, Kij-14f]
72
KijiSchema nutzt die definierten Reader- und Writer-Schemata zur Validierung.
Sofern nicht der Validierungs-Modus NONE konfiguriert wurde, ist es nicht möglich
Daten einzufügen, die nicht einem akzeptierten Writer-Schema entsprechen. [Kij14f]
Je nach konfiguriertem Validierungs-Modus wird die Schema-Evolution ebenfalls
validiert und ist bei entsprechender Konfiguration abwärtskompatibel. Auf diese Art
und Weise werden von KijiSchema mehrere parallel gültige Schema-Versionen
unterstützt. Eine Datenmigration ist dadurch nicht notwendig und aus diesem
Grund wird von KijiSchema hierfür auch keine Unterstützung angeboten. Falls die
Konfiguration eine Datenmigration erforderlich macht, weil die Kompatibilität der
Schemata nicht garantiert wird, muss diese in der Anwendung erfolgen. [Kij-14f]
KijiSchema kann, wie in Tabelle 10 zu sehen, einige Unterstützung für ein
Schema-Management zur Verfügung stellen. Es ist möglich verschiedene EntityTypen inklusive ihrer Struktur zu modellieren. Die Datentypen der Properties
können definiert werden und auch eine Kennzeichnung als Primary Key wird
unterstützt. Weitere Einschränkungen wie Einzigartigkeit oder Existenz können
genauso wenig verwaltet werden, wie Beziehungen zwischen Entities. In einem
Avro-Schema kann allerdings die Existenz einer Property festgelegt werden.
Die verwalteten Metadaten können aus einer gefüllten Datenbank extrahiert
werden und auch für die Schema-Evolution werden einige Methoden zur
Verfügung gestellt.
Als einziges der im Rahmen dieser Arbeit untersuchten NoSQL-Systeme und
aktueller Entwicklungen kann KijiSchema mehrere, parallel gültige SchemaVersionen in vollem Umfang unterstützen.
73
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
Kennzeichnung als Primary Key
Beziehungen
(✓)
✓
✓
(✓)
✓
X
Schema-Extraktion
(✓)
Schema-Evolution
(✓)
✓
Add Entity-Type
Rename Entity-Type
✓
X
Update Entity-Type
(✓)
Delete Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
weiteren Einschränkungen
Single/ Compound Key
Alle Metadaten zu Tabellen, Location
Groups, Column Families & Columns
✓
X
X
✓
Mehrere Schema-Versionen
✓
Unterstützung der Datenmigration
X
Lazy Migration
Nur Datentypen & Existenz, keine
✓
✓
Validierung
Eager Migration
Mit Group-Type Column Families
auch Schema-Evolutions-Validierung
Nicht erforderlich durch kompatible
Schemata
X
X
Tabelle 10: Überblick der von KijiSchema erfüllten Anforderungen an ein SchemaManagement
74
3.3.2
Mongoose
Mongoose ist eine MongoDB Object Data Modeling Library (ODM) für node.js.
Node.js ist eine
Laufzeitumgebung,
Plattform, basierend
zur
auf Google
Entwicklung
Chromes Java-Script
schneller,
skalierbarer
Netzwerkanwendungen. Mongoose stellt für MongoDB eine Möglichkeit zur
Verfügung, um Daten schemabasiert zu modellieren. [Njs-14, Mgo-11]
In Mongoose baut alles auf sogenannten Schemata auf. Jedes Schema wird auf
eine MongoDB-Collection abgebildet und definiert die Struktur der in MongoDB
gespeicherten Dokumente. Schemata werden im JSON-Format gespeichert. Die
Key/Value-Paare eines Schemas definieren die Properties eines Dokumentes
(Key) und ihren Datentyp (Value), der in Mongoose als Schema-Type bezeichnet
wird. Unterstützte Schema-Types sind String, Number, Date, Buffer, Boolean,
Mixed, ObjectID und Array. Mongoose unterstützt auch Nested Objects, so dass
als Value anstelle eines unterstütztem Schema-Type ein Objekt, welches selbst
wieder weitere Key/Value-Definitionen enthält, zugewiesen werden kann. So sind
beliebig tiefe Verschachtelungen möglich. Die von MongoDB genutzten Secondary
Indexes können in Mongoose auch im Schema definiert werden. [Mgo-14a]
Um ein Schema nutzen zu können, muss die Schema-Definition in ein
sogenanntes Model konvertiert werden. Models sind Konstruktoren, deren
Instanzen die einzelnen Dokumente repräsentieren. Das Erzeugen, Speichern in
der Datenbank und Abfragen von Dokumenten geschieht mit Hilfe der Models.
Mongoose-Dokumente werden unverändert auf MongoDB-Dokumente abgebildet.
[Mgo-14a, Mgo-14b, Mgo-14c]
Mongoose Schemata können mit verschiedenen Optionen konfiguriert werden.
Hierzu zählt beispielsweise die Option „autoIndex“, mit der konfiguriert werden
kann, ob Indexe automatisch im Hintergrund oder manuell gesteuert erzeugt
werden. Weiterhin gibt es die Option „capped“, mit der ein Schema in MongoDB
auf eine Capped Collection abgebildet wird. Mit der Konfiguration „strict“ wird
sichergestellt, dass Werte, die dem Model-Konstruktor übergeben werden, jedoch
75
nicht im Schema definiert sind, nicht in der MongoDB-Datenbank gespeichert
werden. [Mgo-14a]
Bevor Dokumente in der zugrundeliegenden MongoDB-Datenbank gespeichert
werden, wird eine Validierung durchgeführt. Diese wird im SchemaType definiert
und wird automatisch asynchron, rekursiv ausgeführt, d.h. ggf. enthaltene SubDokumente
werden
ebenfalls
validiert.
Sub-Dokumente
besitzen
alle
Eigenschaften von „normalen“ Dokumenten, inklusive eigenem Schema, mit der
Ausnahme, dass sie nicht separat gespeichert werden. Sie werden persistiert,
wenn ihr oberstes Parent-Dokument in die Datenbank geschrieben wird. [Mgo14d, Mgo-14e]
Mongoose stellt einige Validierer zur Verfügung. Beispielsweise besitzen alle
Schema-Types
einen
sogenannten
Required
Validator,
mit
dem
die
Exsitenzbedingung sichergestellt wird. Der Schema-Type Number hat außerdem
einen built-in Min-Max Validator, mit dem der Wertebereich eingegrenzt werden
kann. Ähnliche Validierer werden für den Schema-Type String zur Verfügung
gestellt. Mit dem Enum Validator wird gegen eine, im Schema zu definierende,
Menge zulässiger Werte, mit dem Match Validator gegen einen einzelnen,
bestimmten Wert validiert. [Mgo-14e]
Sollten die von Mongoose zur Verfügung gestellten Validierungsmethoden nicht
ausreichen, gibt es, ähnlich zu den CouchDB Validation Functions, die Möglichkeit
eigene Validierer nach Bedarf der Anwendung zu definieren. [Mgo-14e]
In MongoDB existieren keine Joins, dennoch kann es manchmal erforderlich bzw.
sinnvoll sein, wenn Referenzen zu Dokumenten in anderen Collections modelliert
werden können (vgl. Kapitel
3.2.5
- manuelle Referenzen und DBRef). In
Mongoose werden Joins mit Hilfe der sogenannten Population simuliert. Hierdurch
ist es möglich Dokumente anderer Collections in die Ergebnismenge einer Abfrage
aufzunehmen. [Mgo-14f]
76
Als
Population
wird
in
Mongoose
der
Prozess
der
automatischen
Dereferenzierung bezeichnet. Im Schema wird eine Referenz definiert, indem als
Property-Type
Schema.Types.ObjectId
ref: 'name_of_referenced_model'
und
zusätzlich
angegeben
wird.
die
Option
In
dem
referenzierenden Dokument wird die ID/ werden die IDs des/der referenzierten
Dokumente/s gespeichert. Bei einer Abfrage muss die populate()-Methode
aufgerufen werden, damit implizit eine separate Query ausgeführt wird, um die
referenzierten Dokumente mit in die Ergebnismenge aufzunehmen. [Mgo-14g]
Mit Hilfe der in Mongoose definierten Schemata können verschiedene EntityTypen modelliert werden. Diese werden je Schema auf eine MongoDB Collection
abgebildet.
Ein Mongoose-Schema definiert die Struktur der in den Collections gespeicherten
Dokumente. Auch die jeweiligen Properties werden festgelegt und so die Struktur
der Entities im Schema beschrieben. Den Properties wird ein bestimmter Datentyp
zugewiesen und für die Typen Number und String existieren, wie zuvor
beschrieben, sogar Möglichkeiten den Wertebereich weiter einzuschränken (MinMax Validierer, Enum und Match Validierer).
Eine Einzigartigkeitsbedingung kann, wie bei MongoDB, nur durch einen UniqueIndex realisiert werden. Um die Existenz einer Property sicherzustellen, kann der
von Mongoose zur Verfügung gestellte Required Validator genutzt werden. Hierfür
wird nach der Definition des Datentyps einer Property zusätzlich die Option
Required auf den Wert true gesetzt, [Mgo-14h] Beispielsweise:
var user = new Schema(
{
Born: {
type:Date,
required: true
}
}
)
Abbildung 6: Beispiel für die Definition einer
Existenzbedingung in Mongoose
77
Da in MongoDB das _id-Feld für den Primary Key reserviert wird (vgl. Kapitel
3.2.5 ), gibt es auch in Mongoose keine Möglichkeit bestimmte Properties als
Primary Key zu definieren.
Wie bereits erläutert können Beziehungen mittels Population und Zuweisen eines
Wertes für den ref-Parameter in der Schema-Definition umgesetzt werden. Dank
Population unterstützt Mongoose eine automatische Dereferenzierung, sofern für
den Zugriff auf referenzierte Dokumente die populate()-Methode aufgerufen wird.
Eine Extraktion des Schemas, basierend auf einer gefüllten Datenbank, muss
innerhalb einer Anwendung erfolgen, da sie nicht von Mongoose unterstützt wird.
Wie bei Object-Mappern üblich, existieren in Mongoose für die Schema-Evolution
keine expliziten Methoden, sondern die Änderungen müssen direkt im Code
durchgeführt werden. Um beispielsweise einen neuen Entity-Typ hinzuzufügen,
muss ein neues Schema erstellt werden und zur Model-Klasse kompiliert werden.
Eine Validierung gegen das definierte Schema wird von Mongoose zur Verfügung
gestellt. Wie oben beschrieben wird gegen die definierten Datentypen der
Properties und, falls im Schema entsprechend modelliert, auch gegen Existenz
validiert. Für die Schema-Typen Number und String können auch weitere
Einschränkungen festgelegt werden, die mit Hilfe der von Mongoose zur
Verfügung gestellten Validierer geprüft werden. Properties, die nicht im Schema,
sondern zusätzlich in der Model-Klasse, definiert wurden, werden nicht in der
Datenbank gespeichert, außer der Schema-Option „strict“ wurde der Wert false
zugewiesen. Dies wird allerdings nicht empfohlen. In der Default-Konfiguration ist
diese Option mit dem Wert true belegt. Das betroffene Dokument wird dennoch in
der MongoDB-Datenbank gespeichert, jedoch ohne die nicht im Schema
definierten Properties. Eine rekursive Validierung von Subdokumenten ist ebenfalls
verfügbar.
78
Mehrere Schema-Versionen, im besten Fall parallel gültige, werden nicht von
Mongoose unterstützt. Genauso wird keine automatische Datenmigration bei
Schema-Änderungen zur Verfügung gestellt.
Obwohl sich, wie aus Tabelle 11 ersichtlich, Entity-Typen inklusive Struktur und
sonstiger Eigenschaften weitestgehend mit Mongoose modellieren lassen, können
abgesehen von der Validierung keine weiteren Anforderungen an ein SchemaManagement von Mongoose erfüllt werden.
79
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
✓
✓
✓
(✓)
Datentypen
und
Existenz,
Number
String
auch
&
für
weitere
Einschränkungen des Wertebereichs
Kennzeichnung als Primary Key
X
Beziehungen
✓
X
X
X
X
X
X
X
X
X
X
X
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
Mehrere Schema-Versionen
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
Nicht notwendig, da _id-Feld in
MongoDB für Primary Key reserviert
Mittels Population und ref-Option
Nur direkt im Code
✓
X
X
X
X
Tabelle 11: Überblick der von Mongoose erfüllten Anforderungen an ein SchemaManagement
80
3.3.3
Hibernate Object/Grid Mapper
Hibernate Object/Grid Mapper (OGM), nachfolgend kurz OGM genannt, stellt eine
Unterstützung der Java Persistence API (JPA) für NoSQL-Systeme zur Verfügung.
OGM nutzt möglichst viel der Hibernate ORM (Object/Relational Mapping) Engine,
persistiert Entities allerdings in NoSQL-Datenbanksystemen. [OGM-13a, OGM14a]
Momentan befindet sich OGM im Beta-Stadium. Daher werden noch nicht alle
geplanten Mechanismen zur Verfügung gestellt. Derzeit wird, von den innerhalb
dieser Arbeit untersuchten NoSQL-Systemen, nur MongoDB unterstützt. Weiterhin
unterstützt Hibernate OGM u.a. die Key/Value-Stores Infinispan und Ehcache,
sowie die Graph-Datenbank Neo4j. [OGM-13a, OGM-14a, OGM-14b]
Hibernate OGM versucht, sofern sinnvoll anwendbar, möglichst viele Konzepte der
relationalen Datenmodellierung beizubehalten. Dazu gehören z.B. die Abstraktion
von Application Data Model und Persistent Data Model, die Nutzung eines Primary
Keys zur Identifizierung von Entities, sowie der Einsatz von Foreign Keys, um
Beziehungen zwischen zwei Entities herzustellen. [OGM-13b]
Hibernate
OGM
zugrundeliegende
plant
die
Datenbank
Bereitstellung
von
wechseln
können,
zu
Mechanismen,
ohne
die
um
die
komplette
Anwendung neu schreiben zu müssen. So soll es auch möglich sein, innerhalb
einer
Anwendung
verschiedenen
Datenbanksysteme,
auch
NoSQL-
und
relationale Systeme, miteinander zu kombinieren. Außerdem soll eine implizite
Unterstützung der Datenmigration beim Laden der Daten zur Verfügung gestellt
werden. [OGM-13a, OGM-14a]
Da
JPA
genutzt
wird,
werden
Entity-Typen
mittels
@Entity-Annotation
gekennzeichnet. [OGM-14c] In OGM wird jede Entity konzeptuell durch eine Map
<String, Object> repräsentiert. Der Key (der Key/Value-Zuordnung innerhalb der
Map) repräsentiert im Normalfall den Property-Namen, während der Value den
Property-Value als Basis-Datentyp repräsentiert. Es werden Basis-Datentypen
bevorzugt, um die Portabilität zu erhöhen. Die meisten Java Datentypen werden
81
unterstützt. Vom Nutzer definierte Typen (Custom Types gekennzeichnet mit
@Type) werden allerdings nicht unterstützt. [OGM-13b, OGM-13d]
Diese Map, durch die Entities repräsentiert werden, wird je nach eingesetztem
Datenbanksystem abgebildet. In einem Document-Store beispielsweise, wird die
Map durch ein Dokument repräsentiert, in dem jede Dokument-Property einem
Eintrag in der Map entspricht. [OGM-13b]
Der Key, um die Instanz eines Entity-Typs zu identifizieren, besteht aus TabellenName, Primary Key Column Name(s) und Primary Key Column Value(s), wobei
Tabellen-Name eigentlich den Entity-Typ-Namen meint. Beispielsweise die Tabelle
„tbl_user“ mit der PK-Column „userID“: Der Key für die Entity-Instanz mit der
userID=1 ist: „tbl_user,userID,1“). [OGM-13b]
Die meisten Entity-bezogenen Mappings, gekennzeichnet durch die Annotationen
@Entity, @Table, @Column, etc., werden von OGM unterstützt. Allerdings ist
unklar, ob jeweils alle konfigurierbaren Properties wie z.B. @Column (unique=true)
unterstützt werden. Laut [Leo-13] werden scheinbar alle @Column-Properties,
abgesehen von „name“ ignoriert. [OGM-13d]
Auch Beziehungen werden von OGM unterstützt. Es stehen alle Varianten von
Beziehungstypen (@OneToOne, @OneToMany, @ManyToOne, @ManyToMany)
zur Verfügung. Beziehungen werden als Tupel bzw. als Set von Tupeln verwaltet.
OGM speichert die notwendigen Informationen, um von einem Entity zu den
referenzierten Entities zu navigieren. Da für beide Enden der Beziehung diese
Information gespeichert werden muss, werden hier Informationen redundant
gespeichert. So kann sichergestellt werden, dass die referenzierten Daten von
dem referenzierenden Entity ausgehend mittels Key-Lookups erreichbar sind.
[OGM-13b, OGM-13d]
Wie die Speicherung von Beziehungsinformation konkret organisiert ist, hängt vom
spezifischen, eingesetzten NoSQL-Datenbanksystem ab. So kann z.B. in
82
Document-Stores die Information, inklusive der Ids der beiden betroffenen Entities,
in einer der Entities gespeichert werden. [OGM-13b]
Für den Datenzugriff werden von OGM verschiedene Möglichkeiten zur Verfügung
gestellt. Zum einen wird die JPQL (Java Persistence API Query Language)
unterstützt, indem sie in Queries der systemspezifischen Anfragesprache
konvertiert wird. Außerdem werden datenbanksystemabhängige, spezifische
Abfragen unterstützt. Weiterhin gibt es die Möglichkeit Full-Text-Queries, mittels
Hibernate Search als Indexing Engine, auszuführen. Die Criteria API ist bisher
noch nicht implementiert. [OGM-13a, OGM-13e]
Bei der Nutzung von OGM in Verbindung mit MongoDB werden Entities, wie
bereits
für
Document-Datenbanken
erwähnt,
als
MongoDB-Dokumente
gespeichert. Jede Entity-Property wird auf ein Dokument-Feld abgebildet. Mittels
„name“-Property der Annotationen @Table und @Column können Collections und
Dokument-Felder
bei
Bedarf
umbenannt
werden.
Embedded
Objects
(@Embedded) werden als Nested Documents eingebunden. [OGM-13c]
Die Id-Property wird wie bei JPA gewohnt mittels @Id gekennzeichnet. Da in
MongoDB das _id-Feld für den Primary Key reserviert ist, konvertiert Hibernate
automatisch die @Id-Property in das _id-Feld des Dokumentes, egal wie das IdFeld in OGM benannt wurde. Für das Id-Feld können sowohl simple Identifier mit
einem Basis-Datentyp, als auch Embedded Identifier (@EmbeddedID) genutzt
werden. Embedded Identifiers werden als embedded Documents in das _id-Feld
gespeichert. Dadurch können, wie in Abbildung 7 gezeigt, Composite Keys
realisiert werden. [OGM-13c]
83
@Entity
public class News{
@EmbeddedID
private NewsID newsId;
...
}
@Embeddable
public class NewsID implements Serializable{
private String title;
private String author;
...
}
{
„_id“: {
„title“: „How does ...“,
„author“: „Guillaume“
}
}
Abbildung 7: Realisierung eines Composite-Keys in OGM
[OGM-13c]
Der MongoDB-Support von OGM kann mit diversen Properties konfiguriert
werden.
Beispielsweise
wird
mit
Hilfe
von
hibernate.ogm.mongodb.associations.store die Art und Weise definiert,
wie Beziehungen gespeichert werden. Es existieren die drei Varianten IN_ENTITY,
GLOBAL_COLLECTION und COLLECTION. [OGM-13c]
Die Default-Konfiguration ist IN_ENTITY. In diesem Fall speichert OGM die Id(s)
des/r referenzierten Objekte/s, wie in Abbildung 8, in einem Feld bzw. falls
mehrere Objekte referenziert werden in einem Embedded Document. [OGM-13c]
84
@Entity
public class AccountOwner{
@Id
private String id;
@ManyToMany
public Set<BankAccount> bankAccounts;
...
}
{
„_id“: „owner0001“,
„bankAccounts“: [
{„bankAccounts_id“ : „accountXY“ }
]
}
Abbildung 8: Beispiel der Speicherung von Beziehungen in
OGM mit der Konfiguration IN_ENTITY [OGM-13c]
Wird
die
Variante
GLOBAL_COLLECTION
genutzt,
werden
alle
Beziehungsinformationen (aller Beziehungstypen) in einer separaten Collection
gespeichert. Jedes Dokument dieser Collection besteht aus zwei Teilen. Zum
einen dem _id-Feld, in dem die Id-Information (Feld-Name & Value) des
referenzierenden Entities und der Name der Beziehungstabelle gespeichert
werden. Zum anderen dem Row-Feld, in dem in einer Embedded Collection alle
Ids der referenzierten Dokumente gespeichert werden (Feld-Name & Value). Für
Bi-direktionale Beziehungen werden die Informationen redundant, ausgehend von
beiden Seiten der Beziehung, gespeichert. Hibernate OGM hält diese automatisch
konsistent. [OGM-13c]
Die
dritte
Konfigurationsmöglichkeit
ist
COLLECTION.
Hier
wird
pro
Beziehungstyp eine Collection angelegt, in der alle Beziehungsinformationen
dieses Typs gespeichert werden. Diese Strategie ist dem relationalen Modell am
ähnlichsten. Der Name der Collections setzt sich jeweils aus dem Präfix
associations_ und dem Namen der betroffenen Beziehungstabelle zusammen.
85
So können leicht alle Beziehungs-Collections von den Entity-Collections
unterschieden werden. [OGM-13c]
Wie bei GLOBAL_COLLECTION besteht jedes Dokument einer BeziehungsCollection aus _id-Feld und Row-Feld, in dem alle Ids der referenzierten Entities
gespeichert werden. Analog zu GLOBAL_COLLECTION werden auch in diesem
Fall für bi-direktionale Beziehungen zwei Dokumente gespeichert. [OGM-13c]
Für den Datenzugriff existieren in MongoDB zwei verschiedene Möglichkeiten.
Zum einen native MongoDB Abfragen, zum anderen Hibernate Search.
Da OGM Daten in MongoDB nativ speichert, können Abfragen direkt auf der
Datenbank, ohne Einbezug von OGM, mit den von MongoDB zur Verfügung
gestellten Mitteln ausgeführt werden. Nachteil ist, dass in diesem Fall keine
Managed Entites zurückgeliefert werden, sondern die MongoDB-Dokumente an
sich. [OGM-13c]
Alternativ können die Entities mittels Hibernate Search indexiert werden. Hier wird,
unabhängig von MongoDB, eine Menge von Secondary Indexes erzeugt und von
OGM verwaltet. Hierfür müssen die Entities mit der Annotation @Indexed und die
zu indexierenden Felder mit der @Field-Annotation gekennzeichnet werden.
Basierend auf diesem Index können Queries ausgeführt werden. In dieser Variante
werden Managed Entities als Abfrageergebnis zurückgeliefert. [OGM-13c]
Mit Hibernate OGM ist die Beschreibung von Entity-Typen inklusive Properties mit
den JPA-üblichen Annotationen möglich. Verschiedene Datentypen werden
unterstützt und können den Properties zugewiesen werden. Es ist unklar in
welchem Maß Annotation Elements, wie name, unique oder nullable, unterstützt
werden, vor allem in Verbindung mit MongoDB. Abgesehen von name werden
diese Properties scheinbar ignoriert [Leo-13]. Daher ist es nicht möglich EntityProperties weitergehend einzuschränken.
86
Eine Kennzeichnung des Primary Keys erfolgt mit der Annotation @Id. Die
Bezeichnung
des
Entity-Id-Feldes
gilt
je
nach
zugrundeliegendem
Datenbanksystem allerdings ggf. nur innerhalb des Codes. In MongoDB wird der
Key beispielsweise, unabhängig von der Definition, in dem dafür reservierten _idFeld gespeichert. Weiterhin werden Embedded Primary Keys unterstützt, welche
eine Alternative Repräsentation von Compound Keys sind.
Auch Beziehungen können in OGM modelliert und über die oben beschriebenen
drei möglichen Varianten verwaltet werden. Bei bidirektionalen Beziehungen ggf.
redundant gespeicherte Informationen werden von OGM automatisch konsistent
gehalten.
Die verwalteten Metadaten werden zur Validierung von Entity-Typen und ihren
Properties eingesetzt.
Da es sich bei OGM um einen Mapper handelt, existieren keine Methoden zur
Schema-Extraktion oder -Evolution. Diese müssen, auf Code-Basis, in der
Anwendung erfolgen.
Mehrere, bestenfalls parallel gültige Schema-Versionen werden nicht von
Hibernate OGM unterstützt. Ebenso kann OGM bisher keine Unterstützung für
eine ggf. erforderliche Datenmigration bieten. Dies ist allerdings für zukünftige
Versionen geplant. [OGM-14d]
Aufgrund der Tatsache, dass sich Hibernate OGM noch im Beta-Stadium befindet,
können, wie in Tabelle 12 zusammengefasst, bisher nur einige Anforderungen an
ein Schema-Management erfüllt werden. Jedoch sind diverse Erweiterungen
geplant, so z.B. auch die Integration von CouchDB, Cassandra und HBase.
87
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
✓
✓
✓
(✓)
Kennzeichnung als Primary Key
✓
Beziehungen
✓
X
X
X
X
X
X
X
X
X
X
X
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
Mehrere Schema-Versionen
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
✓
X
X
X
X
Nur
Datentypen,
keine
weiteren
Einschränkungen
Nur direkt im Code
Geplant für spätere Version
Tabelle 12: Überblick der von Hibernate OGM erfüllten Anforderungen an ein SchemaManagement
88
3.3.4
Kundera
Kundera ist eine Object-Datastore-Mapping-Library für Datenbanksysteme, die auf
der Java Persistence API (JPA) basiert. Neben relationalen Datenbanken können
in Verbindung mit Kundera die NoSQL-Datenbanksysteme Cassandra, HBase,
MongoDB und CouchDB eingesetzt werden. Allerdings sind alle unterstützten
Versionen der NoSQL-Systeme mittlerweile veraltet. [Kun-14a, Kun-14b]
Die Art und Weise der Datenspeicherung wie auch des Datenzugriffs variieren je
nach genutztem Datenbanksystem. Aber Kundera ermöglicht mittels JPA eine
standardisierte
Zugriffsmethode,
unabhängig
von
der
darunterliegenden
Datenbank. [Kun-14j]
Kundera ist, wie in Abbildung 5 zu sehen, modular aufgebaut. Der Kundera-Core
beinhaltet u.a. die Implementierung des JPA-Interfaces, das die Anwendungen
nutzen.
Darüberliegend
existieren
für
die
unterschiedlichen
unterstützten
Datenbanksysteme verschiedene Module, die jeweils einen eigenen Client nutzen.
Zur Kommunikation mit der jeweiligen Datenbank verwendet der Client Low-Level
Libraries oder spezifische Treiber. [Kun-14c]
Abbildung 9: Kundera Architektur, [Kun-14c]
89
Kundera definiert keine eigene Annotationen, sondern verwendet die StandardJPA-Annotationen. Diese werden, wie in Abbildung 10 dargestellt, je nach
eingesetztem Datenbanksystem unterschiedlich auf die verschiedenen SchemaKonstrukte abgebildet. [Kun-14d]
Abbildung 10: Kundera Annotation-to-NoSQL-Mapping, [Kun-14d]
Mit Hilfe der standardisierten JPA-Annotationen ist es Kundera auch möglich
Polyglot Persistence zu unterstützen. Da Kundera Schnittstellen zu verschiedenen
Datenbanken bietet, ist es innerhalb einer Anwendung möglich die Daten in
verschiedenen Datenbanksystemen zu speichern (z.B. User-Stammdaten in
einem anderen System als Log-Daten). Dies ist im Normalfall bezüglich
Persistierung und Abfragen, die über mehrere verschiedenen Datenbanksysteme
ausgeführt werden müssen, sehr aufwendig. Dank des von Kundera angebotenen,
abstrahierten, einheitlichen Interfaces müssen nur Entities und Beziehungen
definiert werden. Anschließend wird festgelegt, in welchen Datenbanksystemen
die Entity-Typen jeweils gespeichert werden können. Kundera schreibt die Daten
entsprechend der Konfiguration automatisch in die unterschiedlichen Systeme
bzw. fragt die Daten daraus ab. [Kun-14a, Kun-14e]
Kundera legt einige Basis-Regeln für die Nutzung von Annotationen fest.
Beispielsweise müssen Entity-Klassen mit @Entity annotiert werden. Jede EntityKlasse muss genau ein Feld als Primary Key mit @Id kennzeichnen. Des
Weiteren
werden
alle
Felder
mit
den
Annotationen
@Embedded
und
90
@ElementCollection innerhalb der Tabelle (vgl. Mappings in Abbildung 10)
gespeichert z.B. als SuperColumns in Cassandra oder Nested Documents in
MongoDB. [Kun-14d]
Auch Compound Keys werden von Kundera unterstützt. Mit ihnen sind Suchen auf
denormalisierten Daten schneller ausführbar. Compound Keys können wie auch
bei Hibernate OGM mit der Annotation @EmbeddedId definiert werden. Der
jeweilige Key muss allerdings eine Embeddable Entity sein. [Kun-14h]
Ist Cassandra eines der genutzten Datenbanksysteme, muss in der Embeddable
Klasse die Sortierung der Felder beachtet werden, da in Cassandra die
Reihenfolge der Komponenten eines Compound Keys für die Speicherreihenfolge
der Daten entscheidend ist. In der Embeddable Klasse müssen die Felder daher in
der gewünschten Reihenfolge angegeben werden. [Kun-14h]
Weiterhin ist es in Kundera auch möglich Beziehungen im Schema zu definieren.
Es werden alle Varianten uni- und bidirektionaler Beziehungen unterstützt. Sie
werden mittels @OneToOne, @OneToMany, @ManyToOne und @ManyToMany
annotiert. Die Foreign Keys werden von Kundera verwaltet. [Kun-14d, Kun-14e]
Um auch klassische, relationale Datenmodelle unterstützen zu können, wird auch
eine Vererbung innerhalb von Entity-Klassen von Kundera zur Verfügung gestellt.
Eine Parent-Klasse wird mittels @MappedSuperClass gekennzeichnet. Durch die
Integration von Vererbung wird eine Migration von relationalen Systemen zu
NoSQL-Systemen erleichtert. [Kun-14i]
Kundera implementiert ein „DDL auto schema generation“-Feature. Ähnlich wie in
MongoDB müssen Tabellen nicht mehr manuell angelegt oder geändert werden,
sondern werden automatisch von Kundera mit dem Einfügen/ Update von Daten
erzeugt bzw. geändert. [Kun-14g]
Die automatische Schemagenerierung wird konfiguriert, indem in der Persistence
Unit
Definition
innerhalb
der
Datei
persistence.xml
die
Eigenschaft
91
kundera.ddl.auto.prepare
ergänzt
wird.
Es
existieren
die
vier
verschiedenen Konfigurationsmöglichkeiten create, create-drop, update und
validate. Bei der Nutzung von update wird beispielsweise beim Einfügen von
Daten, falls erforderlich, das Tabellen-Schema geändert, sofern die Tabelle bereits
existiert. Andernfalls wird die Tabelle angelegt. Wird dagegen validate ausgewählt,
werden Entities vor dem Speichern gegen das aktuelle Schema der Tabelle
validiert. Falls Entity- und Tabellen-Schema nicht übereinstimmen wird im
Gegensatz zu update das Tabellenschema nicht geändert, sondern es kommt zu
einer Fehlermeldung. [Kun-14g]
Des
Weiteren
muss
die
kundera.ddl.auto.prepare-Property
in
der
Konfiguration angegeben werden, damit die von Cassandra genutzten Secondary
Indexes auch von Kundera unterstützt werden. [Kun-14k]
Für den Zugriff auf die gespeicherten Daten stellt Kundera abhängig vom
zugrundeliegenden
Datenbanksystem
verschieden
JPQL-Konstrukte
(Java
Persistence Query Language) zur Verfügung. Select, Update und Delete werden,
wie in Tabelle 13 ersichtlich, unabhängig vom System, immer unterstützt. [Kun-14f]
92
JPA-QL
Clause
Cassandra
HBase
SELECT
DELETE
✓
✓
✓
✓
✓
✓
ORDER BY
X
X
AND
✓
OR
MongoDB CouchDB
✓
✓
✓
✓
✓
✓
✓
✓
✓
X (Yes with
Lucene)
✓
✓
X
BETWEEN
✓
✓
✓
✓
LIKE
X (Yes with
Lucene)
✓
✓
X
IN
X
X
X
X
=
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
UPDATE
>
<
>=
<=
X
✓
X
✓
✓
Tabelle 13: Von Kundera unterstützte JPQL-Konstrukte nach NoSQL-Systemen, [Kun-14f]
Außerdem wird für den Zugriff auf in Cassandra gespeicherte Daten zusätzlich
Cassandras CQL3 von Kundera unterstützt. [Kun-14l]
Wie bereits beschrieben ist es auch mit Kundera möglich Entity-Typen inklusive
Properties und deren Datentypen zu beschreiben. Dies wird mittels JPAAnnotationen realisiert. Den Wertebereich weiter als mit Datentypen einzugrenzen
scheint nicht möglich zu sein. Inwieweit Annotation Elements, die z.B.
Einzigartigkeit oder Existenz einer Property definieren, tatsächlich modelliert und
93
abgebildet werden können ist nicht in der offiziellen Dokumentation enthalten.
Daher muss davon ausgegangen werden, dass dies nicht unterstützt wird. Also ist
eine weitergehende Einschränkung der Properties nicht möglich.
Primary Keys werden mittels @Id-Annotation definiert. Compound Keys werden
ebenfalls von Kundera unterstützt. Diese werden wie oben beschrieben mit
@EmbeddableId annotiert.
Kundera stellt ebenfalls die Möglichkeit Beziehungen zu modellieren zur
Verfügung und verwaltet die Foreign Keys.
Wie auch schon im Fall von Mongoose und Hibernate OGM werden von Kundera
keine expliziten Operationen zur Schema-Extraktion oder -Evolution zur Verfügung
gestellt. Die Extraktion muss innerhalb einer Anwendung erfolgen. SchemaEvolutionen müssen direkt im Code durchgeführt werden.
Die von Kundera verwalteten Schema-Informationen, werden auch zur Validierung
eingesetzt.
Mehrere, parallel gültige Schema-Versionen, sowie eine Unterstützung der
Datenmigration werden nicht von Kundera angeboten.
Obwohl auch von Kundera, wie in Tabelle 14 zu sehen, viele der Anforderungen
an ein Schema-Management nicht erfüllt werden können, sticht es dennoch
heraus. Kundera ist, unter den hier analysierten Mappern, einer der wenigen, der
bereits erfolgreich mehrere NoSQL-Systeme unterstützt. Zusätzlich werden auch
relationale Datenbanksysteme eingebunden. Kundera unterstützt eine Vielzahl
von Systemen und bietet eine automatische Unterstützung von Polyglot
Persistence, so dass parallel mehrere, verschiedene Datenbanksysteme innerhalb
einer Anwendung ohne nennenswerten Mehraufwand genutzt werden können.
94
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
✓
✓
✓
(✓)
Kennzeichnung als Primary Key
✓
Beziehungen
✓
X
X
X
X
X
X
X
X
X
X
X
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
Mehrere Schema-Versionen
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
Keine genauen Infos zu Constraints
bzw. Annotation Elements
Nur im Code
✓
X
X
X
X
Tabelle 14: Überblick der von Kundera erfüllten Anforderungen an ein SchemaManagement
95
3.3.5
Objectify-Appengine
Objectify-Appengine, kurz Objectify, ist ein Java Interface für den Zugriff auf die im
Google App Engine Datastore gespeicherten Daten. Es ist laut [OAE-14a]
einfacher zu nutzen und transparenter als JDO oder JPA. Ziele von Objectify sind
u.a. die Modellierung verschiedenartiger Datenstrukturen und die Unterstützung
von Schema-Änderungen in-place zur Laufzeit. [OAE-13a, OAE-14a]
Objectify nutzt eigene JPA-/JDO-ähnliche Annotationen, um ein Schema zu
beschreiben. Entity-Klassen werden mit @Entity annotiert und müssen einen
Primary Key mit @Id festlegen. Das Id-Feld kann vom Datentyp Long, long oder
String sein. [OAE-13b]
Es ist auch möglich Parent-Beziehungen mittels @Parent-Annotation zu
kennzeichnen. Innerhalb einer Klasse kann nur ein Parent-Feld existieren. Entities
ohne Parent sind Root-Entities. Alle Entities, die der selben Root-Entity
zugeordnet sind, gehören zur gleichen Entity Group. Gemeinsam mit Entity-Typ
und @Id-Feld definiert das @Parent-Feld den Key der Entity. Dennoch kann der
Name des Parent- oder id-Feldes jederzeit, selbst nachdem bereits Daten
gespeichert wurden, geändert werden. Der Value des Parent-Feldes kann
allerdings nicht einfach geändert werden. Lädt man eine Entity, ändert den ParentValue und speichert diese Entity wieder, erzeugt man eine neue Entity; das alte
Objekt existiert immer noch. [OAE-13b, OAE-13c]
Sollen bestimmte Felder nicht von Objectify in der Datenbank persistiert werden,
können diese als static oder final gekennzeichnet werden. Gleiches gilt auch
für Felder mit der Annotation @Ignore. Im Gegensatz dazu werden Felder, die als
transient gekennzeichnet sind persistiert. [OAE-13b]
Weiterhin werden von Objectify auch Embedded Klassen unterstützt. Hierfür
existiert die Annotation @Embed. Embedded Objekte können in Collections und
Arrays gespeichert werden. Zweidimensionale Strukturen werden in diesem Fall
allerdings nicht unterstützt, daher sind Nested Embedded Arrays oder Collections
innerhalb eines/ einer anderen @Embed Arrays/ Collection nicht möglich.
96
Ebensowenig wird eine Speicherung von Arrays oder Collections nativer
Basisdatentypen innerhalb von @Embed Arrays/ Collections unterstützt. [OAE13b]
Die Alternative zu Embedded Klassen ist die Serialisierung, die mit der Annotation
@Serialize gekennzeichnet wird. Durch Serialisierung lässt sich nahezu jeder
beliebige Java Object Graph speichern. Hierfür müssen alle Objekte des Graphs
serialisierbar sein. Objectify-Annotationen werden innerhalb der serialisierten
Datenstruktur ignoriert, d.h. auch @Ignore-Felder werden gespeichert. Einzig
transiente Felder werden nicht serialisiert. [OAE-13b]
Bevor mit Objectify Daten gespeichert oder abgefragt werden können, müssen alle
Entity-Klassen der Anwendung mit Hilfe der register(entityType.class)Methode registriert werden. Objectify baut dann, basierend auf den registrierten
Entity-Klassen, ein Metamodell auf, mit dem Entities effizient zur Laufzeit
manipuliert werden können. Auch Subklassen müssen explizit registriert werden.
Die einzige Ausnahme bilden Embedded Klassen, die nicht registriert werden
müssen. [OAE-13b]
Um Abfragen durchführen zu können, ist es erforderlich, dass auf allen relevanten
Feldern ein Index definiert wurde. Andernfalls wird bei einer Abfrage eines nichtindexierten Feldes kein Ergebnis zurückgeliefert. Die Indexe werden nicht
automatisch von Objectify angelegt. Sie müssen für die zu indexierenden
Properties explizit mittels @Index-Annotation definiert werden. Beim Speichern
einer Entity wird dann automatisch der Index angelegt. [OAE-14b]
Bei Änderungen der @Index-Annotation in einer Entity-Klasse werden bereits
gespeicherte Daten nicht automatisch migriert. Um den Index zu aktualisieren
müssen die individuellen Entities erneut gespeichert werden. [OAE-14b]
Die Erzeugung und Verwaltung eines Index ist aufwendig. Daher bietet Objectify
auch die Möglichkeit sogenannte Partielle Indexe zu definieren. Sollen
beispielsweise Abfragen generell keine null-Values enthalten, müssen diese also
97
auch nicht indexiert werden. Dies kann mit Hilfe von If-Klassen in der IndexAnnotation festgelegt werden ( @Index(IfNotNull.class) ). Es werden bereits
diverse If-Klassen, für Bedingungen wie z.B. IfNull, IfTrue etc., von Objectify für die
Definition Partieller Indexe zur Verfügungen gestellt. Außerdem gibt es auch die
Möglichkeit eigene If-Klassen zu implementieren. [OAE-14b]
In Objectify ist es weiterhin möglich eine Vererbungshierarchie von miteinander in
Beziehung stehenden Entity-Klassen zu definieren. Das Root-Entity der Hierarchie
muss mit @Entity annotiert sein. Alle Subklassen erhalten die Annotation
@EntitySubclass. Um Abfragen auf Klassen dieser Hierarchie auszuführen,
müssen die Subklassen nicht bekannt sein. Dennoch sind Entities dieser
Subklassen in der Ergebnisliste enthalten. [OAE-13b]
Auch Referenzen werden von Objectify unterstützt. Laut [OAE-13b] wird eine
Beziehung dadurch definiert, dass ein Key als Feld in einem Entity gespeichert
wird. In Objectify existieren zwei verschiedene Key-Klassen. Zum einen die native
Datenbank-Key-Klasse Key, zum anderen Objectifys generische Key-Klasse
Key<?>, die weniger fehleranfällig ist. [OAE-13b]
Allerdings sind auch generische Keys (Key<?>) eher umständlich, wenn mit
Graphen von Entities gearbeitet wird. Daher stellt Objectify sogenannte Ref<?>s
zur Verfügung, die sich ähnlich wie ein Key<?> verhalten, aber mit dem
Unterschied, dass sie einen direkten Zugriff auf das referenzierte Objekt erlauben.
[OAE-13b]
Ref<?>s sollten bestenfalls mit einer @Load-Annotation versehen werden. Durch
die Load-Annotation wird verhindert, dass jedes referenzierte Entity einzeln aus
der Datenbank gelesen wird, indem Objectify den Ladebefehl in eine optimale
Anzahl Batch-Fetches umwandelt. [OAE-13b]
Für den Datenzugriff existieren im GAE Datastore vier Basis-Methoden, auf die
jede Persistence API ihre Methoden abbilden muss. Mittels put() werden Entities
in die Datenbank geschrieben und mit delete() wieder gelöscht. Außerdem
98
können Entities mit der get()-Methode aus der Datenbank geladen werden.
Abfragen werden mit der query()-Methode ausgeführt. [OAE-13c]
Objectify nutzt eine leicht andere Bezeichnung, die aber mit den vier obigen BasisMethoden im Grunde übereinstimmt. Objectify nutzt anstelle der put-Methode die
save()-Methode.
Zum
Löschen
wird
ebenfalls
die
delete()-Methode
eingesetzt. Zum Laden und Abfragen (get- und query-Methode) existiert in
Objectify die load()-Methode. [OAE-13c]
Es werden zwei sogenannte Lifecycle-Callbacks von Objectify unterstützt. Zum
einen @OnLoad, zum anderen @OnSave. Mit diesen Annotationen können
Methoden einer Entity-Klasse gekennzeichnet werden. Diese Methoden werden
dann, je nach Annotation, ausgeführt nachdem die Daten aus der Datenbank
geladen wurden (@OnLoad) bzw. bevor sie in die Datenbank geschrieben werden
(@OnSave). Es können beliebig viele dieser Methoden in einer Entity-Klasse
enthalten sein. Damit ist es z.B. möglich vor dem Speichern selbstdefinierte
Validierungen durchzuführen. [OAE-12a]
Objectify stellt einige Unterstützung für das Schema-Management zur Verfügung.
Das Beschreiben von Entity-Typen inklusive Properties kann umgesetzt werden.
Auch können spezifische Datentypen definiert werden. Weitere Einschränkungen
des Wertebereichs sind dagegen nicht möglich. Allerdings ist es beispielsweise
durch die @Save-Annotation möglich eine entsprechende Einschränkung,
nachdem die Logik explizit definiert wurde, automatisch durch Objectify zu
überprüfen. Einzigartigkeit und Existenz kann nicht spezifiziert werden, sondern
ebenfalls nur über selbstdefinierte Logik und Nutzung der Lifecycle-CallbackAnnotationen realisiert werden.
Primary Keys werden mit der @Id-Annotation festgelegt. Der Feldname kann auch
im späteren Verlauf problemlos geändert werden. Ebenso unterstützt Objectify
auch
die
Modellierung
von
Beziehungen.
Sie
können
mittels
Ref<?>
gekennzeichnet werden. Auch eine automatische Dereferenzierung wird von
Objectify zur Verfügung gestellt.
99
Zur Schema-Extraktion bietet Objectify, ebenso wie für die Schema-Evolution,
keine Methoden. Die Extraktion muss gesondert in einer individuellen Anwendung
erfolgen. Schema-Änderungen müssen direkt im Code vorgenommen werden.
Die Klassen-Definitionen, also mit anderen Worten die Schema-Definition, wird
von Objectify zur Validierung eingesetzt.
Die Möglichkeit explizit mehrere Schema-Versionen zu verwalten existiert in
Objectify nicht. Jedoch können nach einer Schema-Änderung parallel das alte und
neue Schema verwendet werden. [OAE-12b] In den Entity-Klassendefinitionen ist
allerdings nur die neue Schema-Version enthalten, bzw. sind die alten Definitionen
eventuell noch während der Daten-Migrationsphase vorhanden.
Für diese Phase der Datenmigration stellt Objectify einige Unterstützung für Lazy
Migration zur Verfügung.
Wird einem Entity-Typ ein neues Feld hinzugefügt, wird automatisch der DefaultWert gespeichert, falls für das Feld kein Value vorliegt. Wird ein Feld aus einer
Entity-Klasse gelöscht, wird ein entsprechender Value beim Laden ignoriert und
bei neuem Speichern des Entities, wird das gelöschte Feld nicht mehr in die
Datenbank geschrieben. [OAE-12b]
Auch eine Migration nach dem Umbenennen von Properties wird unterstützt. In
der Klassen-Definition erhält das Feld einen neuen Namen und außerdem die
Annotation @AlsoLoad(„oldname“). Bei Abfragen bezüglich dem neuen Feld
werden nun automatisch auch Values mit dem alten Feld-Namen geladen.
Anschließend, wenn das Objekt wieder in die Datenbank zurückgeschrieben wird,
wird nur noch das neue Feld gespeichert. Sollte eine Entity in beiden Feldern
Werte gespeichert haben, kommt es zu einer Fehlermeldung. [OAE-12b]
Für die Daten-Migration nach dem Kopieren oder Verschieben von Properties
existieren keine expliziten Methoden. Allerdings kann mit Hilfe der Annotationen
100
@AlsoLoad, @IgnoreLoad, @IgnoreSave,@OnLoad und @OnSave die Migration
von Objectify unterstützt werden, nachdem die Logik explizit definiert wurde.
[OAE-12b]
Es ist so beispielsweise möglich, nachdem die Klassendefinitionen entsprechend
angepasst wurden, z.B. OnLoad bestimmte Values in Felder des Ziel-Entity-Typs
zu kopieren und im alten Entity-Typ die Felder anschließend nicht mehr zu
speichern. Die Logik muss selbstständig implementiert werden, aber Objectify
kann bei der Ausführung der Migration unterstützen. [OAE-12b]
Auch Objectify-Appengine kann nicht alle Anforderungen an ein SchemaManagement erfüllen (vgl. Tabelle 15). Es ist möglich Entity-Typen inklusive
Struktur
zu
definieren,
Primary Keys festzulegen
und
Beziehungen
zu
kennzeichnen. Für die Schema-Extraktion und -Evolution wird keine Unterstützung
zur Verfügung gestellt. Es ist zwar nicht möglich mehrere gültige SchemaVersionen zu verwalten, dennoch können nach einer Änderung altes und neues
Schema weiterhin parallel genutzt werden. Auch zur Datenmigration stellt Objectify
einige Unterstützung bereit, je nach Art der Änderung muss die Migrationslogik
jedoch manuell definiert werden. Mit Hilfe der verfügbaren Annotationen wird die
(lazy) Migration dann automatisch durch Objectify ausgeführt. Für eager Migration
wird allerdings keine Unterstützung bereitgestellt. Diese muss in der Anwendung
z.B. per Batch-Job erfolgen.
101
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
✓
✓
✓
(✓)
Kennzeichnung als Primary Key
✓
Beziehungen
✓
X
X
X
X
X
X
X
X
X
X
X
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
Validierung
Nur
Datentypen,
keine
weiteren
Einschränkungen
Muss im Code erfolgen
✓
Mehrere Schema-Versionen
(✓)
Unterstützung der Datenmigration
Eager Migration
(✓)
X
Lazy Migration
(✓)
Nach Änderungen: paralleles
Arbeiten mit altem & neuem Schema
Annotationen unterstützen, Logik
muss (meist) selbst definiert werden
Tabelle 15: Überblick der von Objectify-Appengine erfüllten Anforderungen an ein
Schema-Management
102
3.3.6
JSON Schema
JSON Schema ist anders als die bisher analysierten Frameworks, Mapper und
Libraries eine deklarative JSON-basierte Sprache mit der JSON-Dokumente,
unabhängig von einer Programmiersprache oder eines Datenbanksystems, in ihrer
Struktur beschrieben werden können. Da in vielen NoSQL-Systemen JSONDokumente gespeichert werden (können), wird JSON Schema im Rahmen dieser
Arbeit ebenfalls untersucht. [JSc-13a, JSc-14a]
Ein JSON Schema ist selbst wiederum ein JSON-Dokument und definiert
Key/Value-Paare. Da ein JSON Schema-Dokument ein Objekt ist, werden diese
Paare auch als Properties bezeichnet. Die Keys der Key/Value-Paare sind
sogenannte Schema Keywords. [JSc-13a, JSc-14a]
Durch das Keyword $schema wird definiert, dass es sich bei einem JSONDokument um ein JSON Schema handelt. Weiterhin wird durch dieses Keyword
auch festgelegt welche Version des JSON Schema Standards genutzt wird. [JSc13c]
Es ist eine beliebig tiefe Verschachtelung der Properties in einem JSON Schema
möglich. Ein Schema, das kein übergeordnetes Schema besitzt, wird als RootSchema bezeichnet, untergeordnete, nested Schemata als Subschemata. Ein
beliebiger JSON-Value wird als JSON-Instanz oder auch als JSON-Data
bezeichnet. Eine Instanz kann ein oder mehrere Schemata spezifizieren, die für
diese Daten anwendbar sind. Es werden die folgenden sieben, zulässigen
Datentypen definiert: boolean,
integer,
number,
string,
array,
object und null. [JSc-13a]
Mit Hilfe des JSON Schemas wird es Anwendungen ermöglicht JSON-Dokumente
zu validieren. Auch ein leeres Objekt ist ein valides Schema, das jegliche Daten
akzeptiert, solange sie im JSON-Format und von einem der unterstützten
Datentypen sind. [JSc-13a, JSc-13c]
103
Mit dem Keyword type kann der zulässige Datentyp von JSON-Daten im Schema
spezifiziert werden. Der Value des type-Keywords ist entweder ein String (
{„type“: „number“} ), womit einer der von JSON unterstützten Datentypen
spezifiziert wird, oder ein Array von Strings ( {„type“:
„string“]
[„number“,
} ). Im zweiten Fall werden JSON-Daten, die einem dieser
definierten Basistypen entsprechen, akzeptiert. Die Datentypen können mit
unterschiedlichen Properties weiter eingegrenzt werden. [JSc-13c, JSc-13d]
Der Typ null kann, ebenso wie integer, nicht weiter spezifiziert werden. Wenn
als Datentyp nur null definiert wurde, ist „null“ der einzig zulässige Wert. [JSc13b]
Für Strings ist es möglich die minimale bzw. maximale Länge, sowie bestimmte
Pattern und Formate (z.B. date-time) anzugeben, um zulässige JSON-Daten
genauer einschränken zu können. Ebenso kann der Typ Number begrenzt
werden, beispielsweise auf ein Vielfaches einer beliebigen positiven Zahl, z.B. ein
Vielfaches von 10. Weiterhin können Minimum und Maximum des Wertebereichs
festgelegt
werden.
exclusiveMinimum
Es
und
ist
möglich
mittels
exclusiveMaximum
der
zu
boolean
spezifizieren,
Properties
ob
die
Grenzwerte zu den gültigen Values zählen oder nicht. Sind diese Properties true,
zählen die Grenzwerte nicht dazu. [JSc-13b, JSc-13e, JSc-13f]
Arrays werden genutzt um mehrere Elemente gemeinsam, sortiert zu speichern. In
JSON können die Elemente eines Arrays von verschiedenen Datentypen sein.
Daher ist es oft sinnvoll sie ebenfalls gegen ein Schema zu validieren. Dies kann
mit den Keywords item und additionalItems realisiert werden. [JSc-13g]
Generell gibt es in JSON zwei Varianten, wie Arrays genutzt werden. Erste
Variante ist die sogenannte List Validation, eine Liste, nicht notwendigerweise
begrenzter Länge, deren Elemente alle dem gleichen Schema genügen müssen.
Das Schema aller Array-Elemente wird mittels item-Keyword festgelegt. [JSc13g]
104
In
dem
Array
des
Beispiels
in
Abbildung 11 dürfen beispielsweise
nur
Elemente
enthalten
von
sein.
Typ
Das
„additionalItems“
ist
{
„type“ : „array“,
„items“: {
„type“: „number“
}
number
Keyword
für
List
Validation-Arrays nicht relevant. [JSc13g]
}
Abbildung 11: Beispiel für List
Validation in JSON Schema [JSc-13g]
In der zweiten Variante, der sogenannte Tuple Validation, wird das Array als eine
Liste fest definierter Länge, deren Elemente von unterschiedlichen Datentypen
sein können, genutzt. [JSc-13g] Beispielsweise für eine Adresse der Form
[Straßenname, Hausnummer, PLZ, Ort] eignet sich diese Form des Arrays.
In diesem Fall wird wie in Abbildung
12 mit dem Keyword items ein Sub-
{
„type“: „array“,
„items“: [
{„type“:“string“},
{„type“: „string“},
{„type“: „number“},
{„type“: „string“}
]
Array, mit den für die Elemente des
Dokument-Arrays
zulässigen
Schemata, definiert. Die Indizes des
Schema-Arrays entsprechen denen
der Elemente des Dokument-Arrays
und
definieren
so
das
für
das
}
Element jeweils zulässige Schema.
[JSc-13g]
Abbildung 12: Beispiel für Tupel
Validation in JSON Schema [JSc-13g]
Mit dem Keyword additionalItems kann konfiguriert werden, ob weitere
Elemente im Dokument-Array zulässig sind. Ist der Wert false, so können keine
zusätzlichen Elemente hinzugefügt werden. Andernfalls wird als Wert ein Schema
angegeben, das bestimmt von welchem Typ weitere Werte sein müssen. [JSc-13b,
JSc-13g]
Die Länge eines Arrays, unabhängig ob List oder Tuple Validation, kann mit den
Keywords „minItems“ und „maxItems“ festgelegt werden. Außerdem lässt sich mit
105
dem Keyword uniqueItems konfigurieren, ob die Elemente eines Arrays
einzigartig sein müssen (true) oder nicht (false). [JSc-13b, JSc-13g]
Der JSON Schema-Datentyp Object beschreibt eine Menge an Key/ValuePaaren, die als Properties bezeichnet werden. Die Keys der Properties müssen
vom Typ String sein und ein Objekt durch { } begrenzt werden. [JSc-13h]
Die Properties werden mit Hilfe des Keywords properties definiert, dessen
Value ein Objekt ist, in dem jeder Key der Key/Value-Paare der Name einer
Property ist und der Value das JSON Schema dieser Property. [JSc-13b, JSc-13h]
Abbildung 13 zeigt die beispielhafte Definition eines JSON Schema Objects.
{
„type“: „object“,
„properties“: {
„number“: {„type“: „number“},
„streetName“: {„type“: „string“}
}
}
Abbildung 13: Beispiel-Definition eines Objektes in
JSON Schema
Auch für Objekte kann mittels „additionalProperties“ definiert werden, ob
weitere Properties zulässig sind. Default-mäßig sind sie zulässig und es ist ein
leeres Schema definiert, d.h. jedes Schema ist zulässig. Je nach Bedarf kann der
Wert auf false gesetzt werden oder ein bestimmtes Schema definiert werden, dem
alle zusätzlichen Properties genügen müssen. [JSc-13b, JSc-13h]
Um die Existenz bestimmter Properties zu garantieren existiert das Keyword
required. Als Value kann hier, im Anschluss an die Property-Definition, ein Array
beschrieben werden, das die Propertynamen der Required Properties enthält.
Gleichzeitig wird von JSON Schema auch die Möglichkeit, die Anzahl der
Properties mit minProperties und maxProperties einzugrenzen, zur
Verfügung gestellt. [JSc-13b, JSc-13h]
106
Es existieren außerdem diverse weitere Konfigurationsmöglichkeiten, die vom
Datentyp unabhängig sind. Hierzu zählen unter anderem die Metadaten title,
description und default. Weiterhin werden Enums, also Aufzählungen
zulässiger Werte, unterstützt. [JSc-13b, JSc-13i]
Zusätzlich gibt es die Keywords allOf, anyOf und oneOf, die als Value ein
Array erhalten in dem jedes Element ein Schema ist. Je nach Keyword müssen
zulässige JSON-Daten entweder allen, mindestens einem oder genau einem
Schema der im Array definierten Schemata genügen. Darüber hinaus wird von
JSON Schema auch das Keyword not zur Verfügung gestellt, dem ein Objekt, das
ein Schema ist, als Value zugewiesen wird. Valide JSON-Daten dürfen diesem
Schema nicht entsprechen. Auf diese Art und Weise können bestimmte Schemata
ausgeschlossen werden. [JSc-13b, JSc-13j]
Weiterhin werden von JSON Schema Referenzen und die Modellierung von
Abhängigkeiten unterstützt. Eine JSON Referenz erlaubt es einem JSON-Value
andere Values zu referenzieren. Sie ist ein JSON Objekt, das eine Property mit
dem Name $ref enthält, dessen Value ein JSON-String ist. Dieser String enthält
eine URI (Uniform Resource Identifier), die den Ort des referenzierten JSON
Values identifiziert. Die Dereferenzierung erfolgt automatisch. [JSc-12, JSc-13a,
JSc-13k]
Die Modellierung von Abhängigkeiten wird von JSON Schema mit Hilfe des
Keywords dependencies ermöglicht. Es existieren zwei verschiedene Varianten.
Zum einen sogenannte Property Dependencies, bei denen die Existenzbedingung
eines Properties an das Vorhandensein einer anderen Property geknüpft ist. Zum
anderen Schema Dependencies, bei der sich das Schema abhängig von der
Existenz einer Property ändert. [JSc-13b, JSc-13h]
JSON Schema stellt also eine Reihe von Möglichkeiten zur Schema-Definition zur
Verfügung, die tatsächliche Umsetzung, also die Validierung der JSON-Daten
gegen das Schema und die Speicherung in einer Datenbank, muss separat
107
erfolgen. Es gibt eine Reihe von Tools u.Ä. [vgl. JSc-14b], die diesen Prozess
vereinfachen oder automatisieren.
Da sich nicht nur JSON-Dokumente mit Hilfe von JSON Schema beschreiben
lassen, sondern z.B. auch die Daten in Column-Family-Systemen, können mit
JSON Schema Entity-Typen inklusive Properties im Schema modelliert werden.
Wie oben erläutert gibt es zahlreiche Möglichkeiten die Properties bei Bedarf
weiter einzuschränken. Hierzu zählen nicht nur die Angabe des Datentyps,
sondern u.a. auch Grenzwerte für den Value, die Möglichkeit bestimmte
Datentypen auszuschließen, sowie Einzigartigkeits- und Existenzbedingung zu
definieren. Auch Beziehungen können mittels $ref festgelegt und automatisch
dereferenziert werden.
Eine explizite Angabe des Primary Keys ist allerdings nicht möglich. Es kann zwar
eine Id-Property inklusive required-constraint definiert werden, jedoch existiert
keine Möglichkeit im Schema zu definieren, dass hierdurch das JSON-Dokument
identifiziert wird. Dies kann lediglich mit Hilfe einer description im Schema
hinterlegt werden. Diese Information wird aber nicht von JSON Schema
ausgewertet.
Methoden, um das Schema, beispielsweise aus einem bestehenden JSONDokument, abzuleiten, werden nicht zur Verfügung gestellt. Es existieren
allerdings erste Tools, die diese Funktionalität zur Verfügung stellen. [JSc-14b]
Zwecks Schema-Evolution werden auch keine expliziten Methoden zur Verfügung
gestellt. Änderungen am Schema müssen in der Schema-Definition selbst
durchgeführt werden.
Allerdings gibt es mit JSONiq, eine JSON-basierte Abfragesprache, eine
Möglichkeit mit der sowohl die Schema-Extraktion als auch die Schema-Evolution
von JSON Schema-Dokumenten unterstützt werden kann. [Jiq-13, Jiq-14]
108
JSON Schema kann keine automatische Validierung bieten. Da es lediglich dazu
dient die Struktur von JSON-Dokumenten zu beschreiben, muss eine Validierung
separat erfolgen. Es existieren allerdings bereits einige APIs, Tools, etc. um diese
Lücke zu füllen und JSON-Dokumente gegen ein definiertes JSON Schema zu
validieren.
Mit Hilfe der Konfigurationen
anyOf oder
oneOf ist es
möglich mit
entsprechender Verschachtelung verschiedene, parallel gültige Schemata für
einen Entity-Typ zu definieren. Explizit getrennt verwaltet werden diese allerdings
nicht und bilden auch keine Evolutions-Historie ab.
Da es sich um ein reines Beschreibungsformat handelt, dem keine Datenbank
zugrunde liegt, kann JSON Schema logischerweise auch keine Unterstützung für
die Datenmigration anbieten.
Wie in Tabelle 16 zu sehen ist, können fast alle Anforderungen bezüglich der
Schemabeschreibung erfüllt werden. Da JSON Schema keine Implementierung
anbietet, sondern nur die Spezifikation, um die Struktur eines JSON-Dokumentes
zu beschreiben, können nahezu keine weiteren Anforderungen erfüllt werden.
Selbst die Validierung gegen das definierte Schema kann nur mit Hilfe zusätzlicher
Tools erfolgen.
Dennoch ist JSON Schema nicht uninteressant. Vor allem für DokumentDatenbanken, die überwiegend Daten im JSON-Format speichern, könnte die
Möglichkeit der JSON Schema-Beschreibung einige Erleichterungen im Bezug auf
das Schema-Management bieten.
109
Feature
unter-
Erläuterung
stützt
Schemabeschreibung & -speicherung
Entity-Typen
Struktur der Entity-Typen
Einschränkung der Properties
Kennzeichnung als Primary Key
Beziehungen
Schema-Extraktion
Schema-Evolution
Add Entity-Type
Delete Entity-Type
Rename Entity-Type
Update Entity-Type
Add Property
Delete Property
Rename Property
Move Property
Copy Property
✓
✓
✓
✓
X
✓
X
X
X
X
X
X
X
X
X
X
X
Validierung
(✓)
Mehrere Schema-Versionen
(✓)
X
X
X
Unterstützung der Datenmigration
Eager Migration
Lazy Migration
Div. Tools verfügbar
Div. Proprietäre APIs/ Tools
verfügbar
Tabelle 16: Überblick der von JSON Schema erfüllten Anforderungen an ein SchemaManagement
110
3.3.7
Gesamtüberblick aktueller Entwicklungen
Die Schema-Modellierung wird im Grunde von allen analysierten Frameworks,
Mappern etc. sehr gut unterstützt. Es gibt lediglich Einschränkungen bei der
Verfügbarkeit von Constraints und in Mongoose und JSON Schema ist keine
Kennzeichnung des Primary Keys möglich. Außerdem können mit KijiSchema
keine Beziehungen modelliert werden.
Allerdings ist KijiSchema der einzige Aufsatz, der die Schema-Extraktion und
-Evolution zumindest teilweise bereitstellen kann. Es können Entity-Typen und
Properties hinzugefügt oder gelöscht werden. Auch das Umbenennen von
Properties ist mit KijiSchema möglich.
Weiterhin bietet KijiSchema als einziger der analysierten Aufsätze und
Datenbanksysteme eine wirkliche Unterstützung mehrerer Schema-Versionen.
Objectify kann zwar nach Schema-Änderungen mit dem alten und neuen Schema
parallel arbeiten, jedoch werden verschiedene Schemata nicht explizit verwaltet.
Eine Validierung gegen das modellierte Schema wird von allen Aufsätzen
unterstützt. Da JSON Schema ein Format zur Strukturbeschreibung von JSONDokumenten ist, erfolgt hier keine automatische Validierung gegen das Schema.
Diese
kann
aber
mit
Hilfe
zusätzlicher
Libraries,
die
für
diverse
Programmiersprachen verfügbar sind, realisiert werden.
Kundera sticht heraus, weil dieser Mapper viele verschiedene Systeme
unterstützt.
Neben
NoSQL-Datenbanken
können
auch
relationale
Datenbanksysteme eingesetzt werden.
Hibernate
OGM
ermöglicht
zwar
ebenfalls
die
Nutzung
verschiedener
Datenbanksysteme, ist jedoch noch im Beta-Stadium und kann daher die Systeme
jeweils nicht mit vollständigem, geplanten Funktionsumfang unterstützen. Eine
zusätzliche Unterstützung von relationalen Systemen ist in OGM nicht geplant.
111
Möchte man also leicht zwischen relationalen Systemen und NoSQL-Datenbanken
migrieren
können
oder
sogar
verschiedene
Systeme
ohne
merklichen
Mehraufwand parallel nutzen, ist Kundera deutlich besser geeignet.
Zusammenfassend ist festzustellen, dass mit den zusätzlichen Aufsätzen zwar die
Schema-Modellierung deutlich besser unterstützt werden kann als es die meisten
NoSQL-Datenbanksysteme leisten, jedoch können die anderen Anforderungen an
ein Schema-Management auch mit Hilfe dieser zusätzlichen Aufsätze nicht
realisiert werden. Wie aus Tabelle 17 ersichtlich ist, kann einzig KijiSchema die
Anforderungen relativ umfassend erfüllen, ist allerdings auf HBase beschränkt und
nicht unabhängig vom genutzten Datenbanksystem einsetzbar.
112
Feature
Kiji
Mongoose
Schema
Hiber
nate
OGM
Kundera
Objecti
fyJSON
App- Schema
engine
(✓)
✓
✓
✓
✓
✓
Entity-Typen
✓
✓
✓
✓
✓
✓
Struktur der Entity-Typen
✓
✓
✓
✓
✓
✓
(✓)
(✓)
X
(✓)
Schemabeschreibung & -speicherung
Einschränkung der Properties
Kennzeichnung als Primary Key
✓
X
(✓) (✓)
✓
✓
✓
✓
X
✓
X
✓
X
✓
X
✓
X
Schema-Extraktion
(✓)
✓
X
Schema-Evolution
(✓)
X
X
X
X
X
Add Entity-Type
✓
X
X
X
X
X
Delete Entity-Type
✓
X
X
X
X
X
X
X
X
X
X
X
(✓)
X
X
X
X
X
Add Property
✓
X
X
X
X
X
Delete Property
✓
X
X
X
X
X
Rename Property
✓
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
Validierung
✓
✓
X
(✓)
✓
X
✓
X
✓
Mehrere Schema-Versionen
✓
X
(✓)
X
X
X
(✓)
X
Beziehungen
Rename Entity-Type
Update Entity-Type
Move Property
Copy Property
Eager Migration
X
X
X
X
(✓)
X
Lazy Migration
X
X
X
X
(✓)
Unterstützung der Datenmigration
X
X
Tabelle 17: Gesamtüberblick der von den analysierten aktuellen Entwicklungen erfüllten
Anforderungen an ein Schema-Management
113
3.4
Ergebnisse der Analysen
Die analysierten NoSQL-Datenbanksysteme können die Anforderungen an ein
Schema-Management nur ansatzweise erfüllen. Selbst in Verbindung mit
zusätzlichen Aufsätzen ist die Funktionalität nicht ausreichend.
Nativ bringen Cassandra und der GAE Datastore, in Verbindung mit dem Python
SDK, die meiste Unterstützung mit. Nutzt man KijiSchema, das auf HBase
aufsetzt, können sogar noch bessere Resultate erzielt werden. Dennoch können
auch in diesem Fall die Anforderungen nur teilweise erfüllt werden.
Mit Hilfe zusätzlicher Aufsätze lassen sich die Möglichkeiten ein Schema zu
modellieren deutlich verbessern, sofern dies nicht bereits wie von Cassandra und
GAE Datastore unterstützt wird. Auch lässt sich mit Hilfe der analysierten Aufsätze
eine Validierung gegen das modellierte Schema für fast jedes der untersuchten
NoSQL-Systeme realisieren.
Die Schema-Extraktion und -Evolution wird jedoch nur von KijiSchema und in
wenigen Teilen von Cassandra zur Verfügung gestellt. KijiSchema bietet viele
Funktionalitäten eines Schema-Managements an. Daher können für HBase in
Kombination mit KijiSchema viele der Anforderungen an ein Schema-Management
erfüllt werden. Für alle anderen Systeme besteht der Zugewinn durch Nutzung
weiterer Aufsätze hauptsächlich in der Unterstützung der Schema-Modellierung
und Validierung.
Es lässt sich feststellen, dass es mittlerweile diverse Lösungsansätze gibt, um ein
Schema, teilweise auch systemunabhängig, zu modellieren. Aber gerade an
Möglichkeiten zur Schema-Extraktion und -Evolution, sowie einer Automatisierung
der Datenmigration fehlt es. Ebenfalls gibt es kaum Möglichkeiten zur Verwaltung
mehrerer Schema-Versionen. Diese ergeben sich allerdings im Normalfall
automatisch durch die Schema-Flexibilität der NoSQL-Systeme und muss daher
von der Schema-Management-Komponente berücksichtigt werden.
114
Abschließend ist zu sagen, dass im Bereich des Schema-Managements die
bisherige Unterstützung gering ist und noch weitere Entwicklungen notwendig
sind, um ein annähernd ausreichendes Schema-Management zur Verfügung
stellen zu können. Alleine KijiSchema bietet bereits viele der Funktionalitäten, die
von einer Schema-Management-Komponente erwartet werden. Es ist allerdings
auf ein Datenbanksystem beschränkt und Erweiterungen auf andere Systeme sind
bisher nicht geplant.
115
Tabelle 18: Gesamtüberblick der Analyseergebnisse
116
Lazy Migration
Eager Migration
Unterstützung der Datenmigration
Mehrere Schema-Versionen
Validierung
Copy Property
Move Property
Rename Property
Delete Property
Add Property
Update Entity-Type
Rename Entity-Type
Delete Entity-Type
Add Entity-Type
Schema-Evolution
Schema-Extraktion
Beziehungen
Kennzeichnung: Primary Key
Einschränkung d. Properties
Struktur der Entity-Typen
Entity-Typen
Schemabeschreibung
Feature
Cas
san
dra
(✓)
✓
✓
(✓)
✓
X
(✓)
(✓)
✓
✓
X
(✓)
✓
✓
X
X
X
✓
X
X
X
X
HBase
(✓)
(✓)
X
X
X
X
(✓)
(✓)
(✓)
(✓)
X
X
X
X
X
X
X
(✓)
X
X
X
X
✓
✓
✓
(✓)
✓
✓
✓
(✓)
(✓)
X
X
X
✓
X
X
X
X
✓
(✓)
X
X
X
(✓)
(✓)
X
X
X
X
(✓)
(✓)
(✓)
(✓)
(✓)
X
X
X
X
X
X
X
X
(✓)
(✓)
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
GAE
Mongo Couch Couch
Data
DB
DB
base
store
(✓)
✓
✓
(✓)
✓
X
(✓)
(✓)
✓
✓
X
(✓)
✓
✓
✓
X
X
✓
✓
X
X
X
Kiji
Sche
ma
✓
✓
✓
(✓)
X
✓
X
X
X
X
X
X
X
X
X
X
X
✓
X
X
X
X
Mon
goose
✓
✓
✓
(✓)
✓
✓
X
X
X
X
X
X
X
X
X
X
X
✓
X
X
X
X
Hiber
nate
OGM
✓
✓
✓
(✓)
✓
✓
X
X
X
X
X
X
X
X
X
X
X
✓
X
X
X
X
Kun
dera
✓
✓
✓
(✓)
✓
✓
X
X
X
X
X
X
X
X
X
X
X
✓
(✓)
(✓)
X
(✓)
Objec
tify
✓
✓
✓
✓
X
✓
X
X
X
X
X
X
X
X
X
X
X
(✓)
(✓)
X
X
X
JSON
Sche
ma
4
Modulare Schema-Management-Komponente
4.1
Anforderungen an die zu entwerfende SchemaManagement-Komponente
Die in 3.1 definierten Anforderungen an ein Schema-Management sollen auch
von der im Rahmen dieser Arbeit zu entwerfenden Schema-ManagementKomponente erfüllt werden. Zusätzlich werden einige Kriterien definiert, die
ebenfalls von der Komponente erfüllt werden sollen. Außerdem werden ein paar
Punkte beschrieben, die zwar in einer ersten Version der Komponente
vernachlässigbar sind, jedoch in späteren Versionen unterstützt werden sollen.
Bisherige Anforderungen (aus 3.1 )
● Es wird eine geeignete Möglichkeit zur Schemabeschreibung und
-speicherung benötigt. Basierend auf der Definition des Begriffs Schema
aus 2.1 müssen die nachfolgenden Eigenschaften beschrieben werden
können:
•
verschiedene Entity-Typen
•
Struktur der Entity-Typen (Properties)
•
Einschränkungen der Properties
–
Dies umfasst die Unterstützung der benötigten Datentypen (die
konkreten Datentypen sind datenbankabhängig)
–
Die Definition diverser Constraints muss möglich sein. Insbesondere
sind Einzigartigkeits- (unique) und Existenzbedingungen (required,
not null) zu unterstützen
–
Die
weitergehende
Einschränkung
des
Wertebereiches
auf
bestimmte Wertgrenzen (z.B. Value between 0 and 10) sollte
ebenfalls beschrieben werden können
•
Kennzeichnung einer Property als Primary Key
•
Beziehungen zwischen gleichen und unterschiedlichen Entity-Typen
bzw. deren Properties
117
● Schema-Extraktion
•
Ableiten des Schemas auf Basis des existierenden Datenbestandes
● Schema-Evolution
folgende Operationen zur Schemamanipulation müssen bereitgestellt
werden: [vgl. SKS-13]
•
Hinzufügen eines neuen Entity-Typs zum Schema
•
Löschen eines Entity-Typs aus dem Schema
•
Umbenennen des Entity-Typs
•
Update eines Entity-Typs
- Hinzufügen eines Attributes (add property)
- Löschen eines Attributes (delete property)
- Umbenennen eines Attributes (rename property)
- Verschieben eines Attributes von einem Entity-Typ zu einem anderen
(move property)
Kopieren eines Attributes von einem Entity-Typ zu einem anderen
(copy property)
● Es sollte eine Validierung gegen das Schema erfolgen
● Die Koexistenz mehrerer, parallel gültiger Schema-Versionen sollte
unterstützt werden
● Eine Unterstützung der Datenmigration sollte realisiert werden
•
Eager Migration
•
Lazy Migration
118
Zusätzliche Anforderungen
● Die
Schema-Management-Komponente
sollte
eine
automatische
Unterstützung für den Prozess der Schema-Evolution zur Verfügung stellen.
Diese sollte bestenfalls bidirektional realisiert werden:
•
Automatisches Schema-Update, wenn Operationen auf den Daten
ausgeführt werden, die implizit das Schema verändern
•
Automatische Datenmigration, falls explizite Änderungen am Schema
vorgenommen werden
● Unabhängigkeit vom eingesetzten NoSQL-Datenbanksystem
● Die Schemaflexibilität von NoSQL-Systemen muss erhalten bleiben
Ergänzende Anforderungen für eine spätere Version
● Cleansing von NoSQL-Daten im Prozess der Schema-Extraktion
● Zusammenfassung und Optimierung mehrerer Evolutionsschritte bei
Datenmigrationen,
die
mehr
als
eine
Schema-Version
umfassen
(z.B. die Migration von Schema-Version 1 auf Version 10)
4.2
Entwurf der Schema-Management-Komponente
Nachfolgend
wird
zunächst
die
grundsätzliche Architektur
der
Schema-
Management-Komponente beschrieben und anschließend einige zu realisierende
Details festgelegt. Im letzten Teil dieses Unterkapitels wird dann die konkrete
Umsetzung der Komponente mit Hilfe einer Beispielanwendung erläutert.
4.2.1
Architektur
Generell existieren zwei verschiedene Architektur-Varianten. Die SchemaManagement-Komponente kann innerhalb des Datenbanksystems oder als
119
externe zusätzliche Schicht realisiert werden. Um die Unabhängigkeit vom
Datenbanksystem, sowie eine Austauschbarkeit des Systems oder ggf. eine
Einbindung mehrerer verschiedener Systeme zu unterstützen, wird die entworfene
Schema-Management-Komponente, wie in Abbildung 14 dargestellt, als externe
zusätzliche Schicht geplant. [vgl. KSS-14]
Anwendung A
Anwendung B
Schema-Management-Komponente
Schema
Schema
NoSQL-DBMS
Entities
Abbildung 14: Eingliederung der Schema-ManagementKomponente als externe Schicht
Wie auch in [KSS-14] beschrieben, ist es möglich für jede Anwendung individuell
zu entscheiden, ob die Schema-Management-Komponente genutzt werden soll,
oder ein direkter Zugriff auf das NoSQL-Datenbanksystem erfolgen soll, ohne dass
ein Schema-Management erfolgt.
Zur Speicherung des Schemas existieren zwei Möglichkeiten. Zum einen kann das
Schema ebenfalls in der für die Daten genutzten Datenbank abgelegt werden.
Zum anderen können Schemata in einer externen Datenbank gesichert werden.
120
Um die Unabhängigkeit vom Datenbanksystem, z.B. auch zur Vereinfachung einer
Migration auf ein anderes System, zu gewährleisten, ist es sinnvoll die SchemaInformationen extern zu speichern. Somit ist auch eine Unterstützung von Polyglot
Persistence, also die gleichzeitige Nutzung verschiedener Datenbanksysteme,
einfacher realisierbar. Alternativ können je nach genutztem Schema-Format die
Schemata ggf. auch als einfache Dateien auf einem Fileserver gespeichert
werden.
Da die Schema-Management-Komponente nicht in das Datenbanksystem
integriert, sondern als zusätzliche Schicht realisiert wird, ist es auch denkbar dem
Nutzer die Wahl der Art der Schema-Speicherung zu überlassen. So ist es möglich
die Schemata entweder intern im Datenbanksystem, in dem die eigentlichen
Daten gespeichert werden, zu speichern, oder auch extern in einem beliebigen
anderen System, das die Speicherung der Schemata unterstützt.
Um die verschiedenen Anforderungen an ein Schema-Management zu erfüllen,
wird die Schema-Management-Komponente selbst in drei verschiedene Schichten
gegliedert, die in Abbildung 15 dargestellt sind.
121
Abbildung 15: Schichten-Architektur der Schema-Management-Komponente
Oberste Schicht ist die Daten- und Schema-Manipulations-Schicht, die als
Schnittstelle zum Anwender für Operationen auf den Daten und zur SchemaEvolution fungiert. Zweite Schicht ist die Schema-Management-Schicht, die in
verschiedene Komponenten unterteilt wird, um die Anforderungen an das
Schema-Management zu realisieren. Die unterste Schicht, die Schema-ToNoSQL-DB-Schicht, umfasst Datenbank-spezifische Mapper, um die Operationen
auf verschiedene Datenbanksysteme abzubilden.
Wie erwähnt wird die Schema-Management-Schicht in sieben verschiedenen
Manager-Komponenten untergliedert, um die in 4.1 definierten Anforderungen zu
erfüllen. Abbildung 16 gibt einen detaillierteren Blick auf die Architektur der
Schema-Management-Komponente und stellt auch die Kommunikation zwischen
den einzelnen Komponenten dar.
122
Abbildung 16: Architektur der Schema-Management-Komponente
123
Der Data-Access-Manager verarbeitet CRUD-Operationen (Create, Read, Update
und Delete) auf den Daten. Bei modifizierenden Zugriffen, d.h. Einfüge- und
Update-Operationen, löst er eine Validierung durch den Validation-Manager aus.
Werden durch Einfüge- und Update-Operationen implizit Schema-Änderungen
vorgenommen, was bedeutet dass nicht erfolgreich gegen eine der gültigen
Schema-Versionen validiert werden kann, ruft der Data-Access-Manager den
Schema-Evolution-Manager
auf,
um
die
erforderlichen
Schema-Updates
durchzuführen. Die CRUD-Operationen werden dann an die Schema-To-NoSQLDB-Schicht weitergeleitet und auf spezifische Anweisungen der genutzten
Datenbank abgebildet.
Der Schema-Evolution-Manager stellt die in Kapitel 4.1 definierten, benötigten
Evolutions-Methoden bereit. Mit Hilfe dieser Methoden können auch neue
Schemata angelegt werden. Der Manager aktualisiert beim Ändern oder
Hinzufügen von Schemata die Schema-Versionsnummer und die gültigen
Schema-Versionen. Wird durch eine Schema-Änderung eine Datenmigration
erforderlich,
wird
der
Data-Migration-Manager
aufgerufen,
um
diese
durchzuführen. Der Data-Migration-Manager stellt sowohl eager als auch lazy
Migration zur Verfügung.
Aufgabe des Schema-Storage-Managers ist die Speicherung sowie das Auslesen
der verschiedenen Schema-Versionen. Der Speicherort, z.B. externe Datenbank
oder Fileserver, kann vom Nutzer konfiguriert werden. Der Configuration-Manager
verwaltet diese und andere Konfigurations-Informationen.
Der Schema-Extraction-Manager realisiert die Extraktion von Schemata aus einer
bestehenden, gefüllten Datenbank. Diese kann, wie in [KSS-14] beschrieben, mit
Hilfe eines Spanning Graph realisiert werden.
4.2.2
Technische Konzeption
In der Schema-Management-Komponente beschreibt jede konkrete SchemaDefinition einen Entity-Typ bzw. eine mögliche Version des Entity-Typs. Jede
124
Schema-Version wird durch eine eindeutige, fortlaufende Versionsnummer und
den Entity-Typ identifiziert. Dadurch ist auch die Rekonstruktion einer SchemaEvolutions-Historie
realisierbar.
Für
die
entworfene
Schema-Management-
Komponente wird festgelegt, dass jedes Schema die Properties schemaVersion
und entityType
enthalten muss, in denen Versions-ID und Entity-Typ
gespeichert werden. Diese Properties müssen als required gekennzeichnet
sein.
Da die Kennzeichnung einer Property als Primary Key zwar nicht in allen NoSQLSystemen erforderlich, aber durchaus für verschiedene Datenbanksysteme
unumgänglich ist, setzt die Schema-Management-Komponente voraus, dass
innerhalb der Schema-Definition eine Property namens entityID existieren
muss. Alternativ könnte von der Schema-Management-Komponente definiert
werden, dass eine Property mit der Beschreibung „Primary Key“ enthalten sein
muss. So könnte der Primary Key innerhalb der Anwendung einen beliebigen
Namen tragen, wird je nach Datenbanksystem allerdings ggf. auf ein Feld mit
einem anderen Namen abgebildet, z.B. in MongoDB auf das Feld _id. In jedem
Fall muss die Primary-Key-Property als required im Schema modelliert werden.
Da mehrere parallel gültige Schema-Versionen von der Schema-ManagementKomponente unterstützt werden sollen, werden für die Entity-Typen, ähnlich wie
bei KijiSchema, Listen gültiger Schemata geführt. Anders als in KijiSchema
werden diese Listen im Schema der jeweiligen Entity-Typen verwaltet und nicht für
jede konkrete Entity-Ausprägung. Für die Entity-Typen wird daher zusätzlich eine
required Property von einem mehrelementigen Datentyp, z.B. Array, mit dem
Namen acceptedSchemas definiert. Damit die Rekonstruktion einer kompletten
Schema-Evolutions-Historie möglich ist, kann zusätzlich noch eine Liste aller
jemals
genutzter,
nicht
notwendigerweise
noch
gültiger
Schemata,
usedSchemas, definiert werden.
Die Unterstützung mehrerer Schema-Versionen, die auch parallel gültig sein
können, muss auch bei der Validierung berücksichtigt werden. Es muss also
gegen alle gültigen Schemata geprüft werden, bis eine Version gefunden wird,
125
gegen die die Daten erfolgreich validiert werden, oder alle Validierungsversuche
erfolglos verlaufen sind. Im letzten Fall sind zwei Vorgehensweisen denkbar. Zum
einen können die Daten als invalid abgelehnt werden. Zum anderen kann implizit
durch die Daten eine neue Schema-Version definiert werden, die vom SchemaEvolution-Manager entsprechend zu realisieren ist. Die Schema-ManagementKomponente führt aus diesem Grund die zwei verschiedenen Validierungs-Stufen
strictValidation (Ablehnung invalider Daten) und updateValidation
(Schema-Update bei invaliden Daten)
ein. Eine weitere Verfeinerung mit
zusätzlichen Zwischenstufen ist denkbar.
Entities erhalten eine Property namens validSchemaVersion, die die aktuellste
Schema-Version angibt, gegen die diese Entity-Ausprägung validiert werden kann.
Diese Property muss, wie schon die Schema-Versions-ID, der Entity-Typ und
Primary Key, sowie die Liste gültiger Schema-Versionen, als required
gekennzeichnet werden. Die Angabe dieser Property bedeutet nicht automatisch,
dass nicht auch andere Schema-Versionen für diese konkrete Entity gültig sein
können. Um allerdings alle passenden Schema-Versionen zu speichern, müsste
beim Einfügen der Daten immer eine Validierung gegen alle für diesen Entity-Typ
gültigen Schema-Versionen erfolgen, was das Einfügen jedoch zusätzlich
verzögern würde. Aus diesem Grund wird hierauf verzichtet.
Die im Zuge der Schema-Evolution erforderliche Datenmigration soll vom User
konfiguriert werden können. Die Schema-Management-Komponente muss sowohl
Eager als auch Lazy Migration unterstützen. Für die entworfene SchemaManagement-Komponente wird eine Entity-Typ-basierte Migrations-Konfiguration
gewählt. Daher erhalten Entities die zusätzliche Property useEagerMigration
vom Typ boolean, mit der die Art der Migrationsstrategie festgelegt wird. Diese
wird, wie u.a. die Schema-Versions-ID, als required Property definiert. In der
Default-Konfiguration wird sie mit dem Wert true belegt und somit Eager
Migration festgelegt, da dies für eine erste Version der Schema-ManagementKomponente einfacher zu implementieren ist.
126
4.2.3
Umsetzung
Schema-Modellierung
Es existieren verschiedene Möglichkeiten ein Schema zu modellieren. Dies haben
auch die im Rahmen dieser Arbeit durchgeführten Analysen gezeigt. Es gibt z.B. in
Cassandra die systemeigene CQL mit der das Schema definiert wird. Mongoose
und KijiSchema beschreiben ein Schema mit Hilfe des JSON-Formats. Kundera,
Hibernate OGM und Objectify-Appengine nutzen JPA-Annotationen bzw. JPAähnliche Annotationen.
Als Format zur strukturellen Beschreibung von JSON-Dokumenten etabliert sich
JSON Schema besonders im Umfeld der Webanwendungen. Weiterhin kann es
viele der in 4.1 beschriebenen Anforderungen an die Modellierung erfüllen und
bietet u.a. eine weitreichende Unterstützung von Constraints. Viele NoSQLSysteme speichern Daten als JSON-Dokumente und auch die Datenstrukturen
anderer Systeme lassen sich mit Hilfe von JSON modellieren. Zusätzlich ist die
Beschreibung mittels JSON Schema, anders als z.B. JPA-Annotationen,
unabhängig von einer bestimmten Programmiersprache. Daher wird JSON
Schema als Format zur Schema-Beschreibung der entworfenen SchemaManagement-Komponente gewählt.
Zur besseren Verständlichkeit wird eine Beispiel-Anwendung eingeführt, um die
Funktionsweise der Schema-Management-Komponente zu verdeutlichen. In einer
Datenbank sollen Informationen zu der Fernsehserie „Doctor Who“ verwaltet
werden. Hierzu werden Daten zu den verschiedenen Inkarnationen des Doktors,
dem Hauptcharakter der Serie, gespeichert. Zusätzlich sollen Informationen zu
den Schauspielern, die die jeweilige Inkarnation des Doktors verkörpern,
gespeichert werden.
127
Abbildung 17: UML-Klassendiagramm der Doctor Who-Datenbank mit den beiden
Entity-Typen InkarnationDesDoktors und Schauspieler
Eine Inkarnation des Doktors wird mit eindeutiger EntityID identifiziert. Zusätzlich
wird eine Beschreibung des Aussehens und der typischen Kleidung dieser DoktorInkarnation sowie die Episoden, in denen diese Inkarnation mitspielt, verwaltet.
Ein Schauspieler hat eine eindeutige EntityID, sowie Vor- und Nachnamen.
Außerdem ein Geburtsdatum und bei Bedarf ein Sterbedatum. Zusätzlich werden
optional andere Rollen, die dieser Schauspieler gespielt hat, gespeichert. Ein
Schauspieler verkörpert genau eine Inkarnation des Doktors.
Die folgende Abbildung 18 zeigt die zu diesen beiden Entity-Typen gehörende
JSON Schema-Definition. Informationen zur Inkarnation des Doktors werden
innerhalb eines Objektes gespeichert. Informationen zum Schauspieler werden
verschachtelt, als zusätzliche Property vom Datentyp object innerhalb der
Doktor-Inkarnation abgelegt. Für alle Properties werden Datentypen festgelegt und
die entityID jeweils mit einer Existenzbedingung versehen.
128
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type":"object",
"properties":{
"entityID": {"type":"integer"},
"aussehen":{"type":"string"},
"kleidung":{"type":"string"},
"episoden":{
"type":"array",
"items":{"type":"string"}
},
"schauspieler":{
"type":"object",
"properties":{
"entityID":{"type":"integer"},
"vorname":{"type":"string"},
"nachname":{"type":"string"}
...
},
"required":["entityID"]
}
},
"required":["entityID", "schauspieler"]
}
Abbildung 18: Beispielhafte JSON Schema-Definition der beiden Entity-Typen
InkarnationDesDoktors und Schauspieler
Alternativ wäre es auch möglich für die beiden Entity-Typen, anstelle dieses
verschachtelten Modells, getrennte Schemata zu definieren und die Beziehung
zwischen den beiden Entity-Typen mit Hilfe von Referenzen zu modellieren.
Es ist anzumerken, dass sich JSON Schema auf sieben verschiedene, zulässige
Datentypen beschränkt. Das von der Anwendung genutzte Datenbanksystem stellt
evtl. mehr oder andere Datentypen zur Verfügung, die mit JSON Schema nicht
direkt modelliert werden können. Daher ist die Schema-Modellierung auf die
verfügbaren
Datentypen
begrenzt.
Diese
sind
im
Normalfall
allerdings
129
ausreichend, um die Daten zu beschreiben. Außerdem lassen sich durch Arrays
und Objekte beliebig tiefe Verschachtelungen definieren.
Obwohl KijiSchema und Mongoose zwar das JSON-Format zur SchemaModellierung nutzen, ist es nicht sinnvoll Teile davon für die Beschreibung eines
Schemas in der Komponente wiederzuverwenden. Da keines dieser Systeme das
JSON Schema Format nutzt, wären zu viele Anpassungen notwendig. Zur
Modellierung von JSON Schema-Dokumenten ist es ausreichend diese z.B. in
einem Texteditor zu erstellen.
Um die oben unter „Technische Konzeption“ beschriebenen Eigenschaften zu
realisieren, können die zusätzlich erforderlichen Properties in einem Meta-Schema
definiert werden, gegen dass alle erstellten JSON Schema-Dokumente validiert
werden müssen. Des Weiteren muss vom Schema-Validation-Manager ebenfalls
sichergestellt werden, dass das Schema ein valides JSON Schema-Dokument ist,
das der JSON Schema Spezifikation entspricht. Unter [JSc-14c] steht ein MetaSchema zur Verfügung, das die Definitionen aller JSON Schema-Keywords
zwecks Validierung enthält und um eigene Property-Definitionen erweitert werden
kann. Weiterhin existieren diverse Libraries die zu diesem Zweck genutzt werden
können. [JSc-14c, JSO-14]
Das Default-Meta-Schema ([JSc-14c]) wird, wie in Abbildung 19 zu sehen ist, um
die Definitionen der für die Schema-Management-Komponente zusätzlich
festgelegten Properties erweitert.
130
{{
...
...
//(Fortsetzung)
//(Fortsetzung)
...
...
"type":
"type": "object",
"object",
"properties":
"properties": {{
"entityType":
"entityType":
"properties":
"properties": {{
"type":
"type": "object",
"object",
{"type":"string"},
{"type":"string"},
"schemaVersion":
"schemaVersion":
"additionalProperties":
"additionalProperties":
{"type":"integer"},
{"type":"integer"},
"entityID":
"entityID":
{{ "$ref":
"$ref": "#"
"#" },
},
"required":
"required":
{"type":"integer",
{"type":"integer",
"acceptedSchemas":
"acceptedSchemas":
["entityID",
["entityID",
"validSchemaVersion"],
"validSchemaVersion"],
{{
"type":"array",
"type":"array",
"default":
"default": {}
{}
},
},
"items":
"items":
{"type":"integer"}
{"type":"integer"}
},
},
"usedSchemas":
"usedSchemas":
...
...
{{
"type":"array",
"type":"array",
"required":
"required":
["entityType",
["entityType",
"items":
"items":
{"type":"integer"}
{"type":"integer"}
"schemaVersion",
"schemaVersion",
},
},
"validSchemaVersion":
"validSchemaVersion":
"acceptedSchemas",
"acceptedSchemas",
{"type":"integer"},
{"type":"integer"},
"useEagerMigration":
"useEagerMigration":
"useEagerMigration"],
"useEagerMigration"],
"usedSchemas",
"usedSchemas",
{{
"type":"boolean",
"type":"boolean",
"default":
"default": true
true
},
},
...
...
"dependencies":
"dependencies":
...
...
}}
Abbildung 19: Erweiterung des Meta-Schemas
Da die oben beschriebenen, ergänzenden Properties für alle Entity-Typen, die mit
der Schema-Management-Komponente verwaltet werden, erforderlich sind, ist
diese Meta-Schema-Definition von der hier eingeführten Beispiel-Anwendung
unabhängig. Bei Bedarf kann sie zusätzlich mit weiteren Definitionen erweitert
werden.
131
Durch die Einführung des Meta-Schemas hat sich die JSON Schema-Definition
der Entity-Typen InkarnationDesDoktors und Schauspieler wie folgt
verändert:
{"$schema": "http://json-schema.org/draft-04/schema#,
"entityType": "InkarnationDesDoktors",
"schemaVersion": 1,
"acceptedSchemas": [1],
"usedSchemas": [1],
"useEagerMigration":true,
"type":"object",
"properties":{
"entityID": {"type":"integer"},
"validSchemaVersion": {"type":"integer"},
"aussehen":{"type":"string"},
"kleidung":{"type":"string"},
"episoden":{"type":"array","items":{"type":"string"}},
"schauspieler":{ "type":"object",
"properties":{
"entityID":{"type":"integer"},
"validSchemaVersion"::{"type":"integer"},
"vorname":{"type":"string"},
"nachname":{"type":"string"}
...},
"required":["entityID","validSchemaVersion"]
}
},
"required":["entityID","validSchemaVersion", "schauspieler"]
}
Abbildung 20: Beispielhafte JSON Schema-Definition der beiden Entity-Typen
InkarnationDesDoktors und Schauspieler nach Einführung des Meta-Schemas
Validierung
Beim Einfügen von Daten müssen die Entities gegen gültige Schema-Versionen
validiert
werden.
Hierfür
existieren
verschiedene
Libraries
für
diverse
Programmiersprachen (u.a. Python, Java, JavaScript, PHP, …). Diese können
vom Validation-Manager für die Validierung genutzt werden. [JSc-14b]
132
Um die Validierung von einzufügenden Daten zu verbessern, sollten dem Nutzer
jeweils zwei verschiedene Einfüge- bzw. Update-Methoden zur Verfügung stehen eine Methode inklusive expliziter Angabe der zu nutzenden Schema-Version, eine
ohne Schema-Versions-Angabe. Wird eine Schema-Version angegeben, erfolgt
die Validierung nur gegen diese Schema-Version, selbst wenn die Validierung
fehlschlägt und die Daten einer anderen Version genügen würden. Die Methode
ohne Schema-Versions-Angabe validiert nacheinander gegen alle gültigen
Schema-Versionen des Entity-Typs, angefangen bei der aktuellsten, bis eine
passende Version gefunden wurde, oder die einzufügenden Daten als invalid
erklärt werden.
Wie oben beschrieben stellt die Schema-Management-Komponente die beiden
unterschiedlichen
Validierungsmodi
updateValidation
zur Verfügung. Zur Realisierung des automatischen
Schema-Updates
Fall
im
von
invaliden
strictValidation
Daten
bei
der
Nutzung
und
von
updateValidation, kann eventuell Kunderas „DDL auto schema generation“Feature angepasst werden. Ob eine entsprechende Anpassung sinnvoll ist, oder
der Aufwand den einer Eigenentwicklung übersteigt, muss allerdings tiefergehend
evaluiert werden. Wird das Feature wiederverwendet, ist es in diesem Fall nicht
unbedingt notwendig die oben genannten Validierungs-Stufen zu definieren. Es
können auch Kunderas Konfigurationsmöglichkeiten
update und validate
genutzt werden.
Um die Schema-Flexibilität von NoSQL-Systemen nicht zu verlieren, müssen die
verschiedenen gültigen Schema-Versionen nicht zwangsweise miteinander
kompatibel sein. So ist es weiterhin möglich, wenn auch meist nicht sonderlich
sinnvoll, dass zwei Entities vom gleichen Typ, mit Ausnahme der im Meta-Schema
definierten Eigenschaften, komplett unterschiedliche Properties besitzen.
Indem Properties explizit als required definiert werden müssen, wird die
Schema-Flexibilität der Schema-Management-Komponente ebenfalls unterstützt.
Alle nicht auf diese Weise gekennzeichneten Properties sind optional. Des
133
Weiteren ist es möglich mit Hilfe des Keywords anyOf den Properties
verschiedene, akzeptierte Datentypen zuzuweisen. Dies bedeutet, dass zwei
Entities vom gleichen Typ zwar die selben Properties, jedoch mit unterschiedlichen
Datentypen, besitzen können. Auch die Unterstützung mehrerer parallel gültiger
Schema-Versionen trägt zum Erhalt der Schema-Flexibilität bei.
Soll in einer späteren Version der Schema-Management-Komponente eine
Validierung der Schema-Evolution wie in KijiSchema eingeführt werden, können
die verwalteten Listen gültiger, sowie insgesamt genutzter, nicht notwendigerweise
noch gültigen Schema-Versionen hierfür genutzt werden. Es sollten wie in
KijiSchema verschiedene Grade der Schema-Evolutions-Validierung realisiert
werden. So kann der User konfigurieren in welchem Ausmaß gültige Schemata
kompatibel sein müssen.
Da sich die Schema-Modellierung von KijiSchema und JSON Schema relativ stark
unterscheidet, ist es voraussichtlich nicht sinnvoll die Komponente zur SchemaUpdate-Validierung abgeändert wieder zu verwenden. Es ist anzunehmen, dass
der Anpassungsaufwand ähnlich hoch wie der einer Eigenentwicklung ist.
Allerdings können sowohl die verschiedenen Schema-Update-Validierungs-Modi
als auch die konkrete Implementierung der TableLayoutUpdateValidatorKlasse als Vorbild für eine eigene Schema-Evolutions-Validierungs-Komponente
dienen. [Kij-13, Kij-14f]
Datenmanipulation
Damit der Zugriff auf die Daten über die Schema-Management-Komponente
realisiert werden kann und so eine Validierung gegen definierte SchemaVersionen, sowie ggf. eine automatische Schema-Evolution möglich sind, muss
eine
datenbanksystemunabhängige Anfragesprache zur Verfügung gestellt
werden. Um die Lernkurve möglichst flach zu halten, ist eine SQL-ähnliche
Sprache zu bevorzugen. Als einziges der im Vorfeld analysierten Systeme bietet
Cassandra mit der CQL eine geeignete Sprache für den Zugriff auf die Daten.
Theoretisch ist es möglich, die genutzten Sprachkonstrukte für die CRUD134
Operationen
anzupassen
und
für
die
Schema-Management-Komponente
wiederzuverwenden. Die Syntax der Anweisungen wird dahingehend angepasst,
dass anstelle der in Cassandra genutzten Table der Entity-Typ und anstelle von
Columns nun Properties verwendet werden. Allerdings sind darüber hinaus
weitere Änderungen erforderlich. Es muss detaillierter analysiert werden, wie
umfassend die erforderlichen Anpassungen sind und ob evtl. eine eigene
Implementierung nach dem SQL-/ CQL-Vorbild effizienter umzusetzen ist.
Eine mögliche, an SQL/ CQL angelehnte, Anweisung zum Einfügung einer neuen
Inkarnation des Doktors könnte wie in Abbildung 21 aussehen.
INSERT INTO InkarnationDesDoktors (entityID, aussehen,
kleidung, episoden,
schauspieler(entityID,
vorname, nachname))
VALUES (10, „braune Haare“, „brauner Anzug, Krawatte,
Chucks“, [„14-60“, „103“],
(5, „David“, „Tennant“));
Abbildung 21: Beispiel Insert-Statement, angelehnt an SQL bzw. CQL
Mit dieser Anweisung wird die folgende Entity-Ausprägung in die Datenbank
geschrieben:
{
"entityType": "InkarnationDesDoktors",
"entityID": 10,
"validSchemaVersion":
1,
"aussehen":"braune Haare",
"kleidung":"brauner Anzug, Krawatte, Chucks",
"episoden":["14-60", "103"],
"schauspieler":{
"entityID":5,
"validSchemaVersion": 1,
"vorname":"David",
"nachname":"Tennant"
}
}
Abbildung 22: Beispiel-Entity vom Typ InkarnationDesDoktors
135
Je nach genutztem Datenbanksystem müssen die Methoden der Anfragesprache
in der Schema-To-NoSQL-DB-Schicht mit Hilfe von spezifischen Mappern auf
Operationen der bestimmten Datenbank abgebildet werden. Hierfür können
Funktionalitäten der Datenbanksystem-spezifischen Module von den beiden
systemübergreifenden Mappern Hibernate OGM und Kundera, nach vorheriger
Anpassung, genutzt werden. Sollen weitere, von diesen Mappern nicht
unterstützte Datenbanksysteme, von der Schema-Management-Komponente
eingesetzt werden können, müssen die entsprechenden Mapper selbst entwickelt
werden, falls nicht anderweitig entsprechende Vorlagen existieren.
Schema-Evolution
Zur Realisierung des Schema-Evolution-Managers ist es erforderlich eine
Schema-Evolutions-Sprache
zu
definieren.
Es
existieren
verschiedene
Möglichkeiten für die Umsetzung. Da als Format für die Schema-Beschreibung
JSON Schema gewählt wurde, können Schema-Änderungen mit Hilfe von JSONiq
durchgeführt werden. Damit die entworfene Schema-Management-Komponente
nicht auf ein bestimmtes Schema-Format beschränkt ist, wird jedoch die Nutzung
einer unabhängigen Evolutionssprache bevorzugt.
Obwohl KijiSchema und Cassandra unter den analysierten Systemen die SchemaEvolution am besten unterstützen, müssten viele Anpassungen und Ergänzungen
vorgenommen werden, um die in 4.1 definierten Anforderung an die SchemaEvolution erfüllen zu können. Aufgrund der Unterschiede in der Schema-Definition
von KijiSchema und JSON Schema ist zu erwarten, dass eine Wiederverwendung
der von KijiSchema zur Verfügung gestellten Evolutions-Operationen zu aufwendig
und kompliziert ist. Da auch die CQL die Anforderungen nur teilweise erfüllen
kann, eignet sich diese ebenfalls nicht zur Nutzung in der entworfenen SchemaManagement-Komponente und kann allenfalls als Anregung dienen.
Zur Nutzung in der Daten- und Schema-Manipulations-Schicht muss also eine
eigene Evolutionssprache implementiert werden. Intern kann diese dann, soweit
verfügbar, auf JSONiq-Methoden abgebildet werden, um Änderungen an den
136
JSON Schema-Dokumenten vorzunehmen. Auf diese Weise lässt sich das
Schema-Format bei Bedarf relativ leicht austauschen.
Eine Variante ist die Implementierung einer SQL-ähnlichen Evolutionssprache, mit
Operationen
Alternativ
ist
wie
CREATE
es
denkbar
EntityType
die
in
[WITH
[SKS-13]
List<Properties>].
entwickelte
NoSQL-Schema-
Evolutionssprache zu implementieren. Sie besteht aus nur wenigen Befehlen, mit
denen alle erforderlichen Evolutions-Operationen ausgeführt werden können.
Daher ist sie schnell zu erlernen und relativ einfach implementierbar.
Für
die
initiale
Schemadefinition
können
die
Methoden
der
Schema-
Evolutionssprache ebenfalls genutzt werden, da die Definition eines neuen
Schemas dem Hinzufügen eines neuen Entity-Typs entspricht.
In dem vorgestellten Beispiel-Szenario sollen zukünftig auch Daten zu den
Begleitern des Doktors verwaltet werden. Außerdem ist beabsichtigt die
Informationen über die Darsteller der Doktor-Inkarnationen separat zu speichern.
Abbildung 23 zeigt das aktualisierte Klassen-Diagramm. Um diese Änderungen
umzusetzen existieren verschiedene Möglichkeiten.
Abbildung 23: Erweitertes UML-Klassendiagramm der Doctor Who-Datenbank mit
den Entity-Typen InkarnationDesDoktors, Schauspieler und Begleiter
137
Zunächst muss ein neuer Entity-Typ Begleiter hinzugefügt werden. Damit die
Übersichtlichkeit erhalten bleibt, werden für jeden Entity-Typ in Zukunft eigene
Schema-Beschreibungen angelegt, auf die dann bei Bedarf verwiesen werden
kann. Für die beiden bisherigen Entity-Typen InkarnationDesDoktors und
Schauspieler müssen die Schema-Informationen entsprechend aktualisiert
werden. Hierfür muss die Schema-Informationen des Typs Schauspieler, die
bisher im Inkarnations-Schema verschachtelt enthalten sind, in eine eigene
Schema-Definition verschoben werden. Alternativ können auch alle SchemaDefinitionen in einem einzigen JSON Schema-Dokument enthalten sein und
mittels id-Tag unterschieden werden.
Basierend auf der Schema-Evolutionssprache aus [SKS-13] und CQL müssen die
folgenden Evolutionsoperationen durchgeführt werden, um die geforderten
Schema-Updates zu realisieren:
Hinzufügen des Entity-Typs Begleiter inklusive Properties
add Entity Begleiter;
alter Begleiter add entityID integer required ;
alter Begleiter add vorname string;
alter Begleiter add nachname string;
alter Begleiter add episoden array[string];
alter Begleiter add schauspieler Schauspieler;
Hinzufügen des Entity-Typs Schauspieler inklusive Verschieben der in
InkarnationDesDoktors enthaltenen Properties
add Entity Schauspieler;
move InkarnationDesDoktors.schauspieler.entityID
Schauspieler.entityID
to
move InkarnationDesDoktors.schauspieler.vorname to
Schauspieler.vorname
where(InkarnationDesDoktors.schauspieler.entityID =
Schauspieler.entityID)
move InkarnationDesDoktors.schauspieler.nachname to
Schauspieler.nachname
where(InkarnationDesDoktors.schauspieler.entityID =
Schauspieler.entityID)
...
138
Aktualisieren des Entity-Typs InkarnationDesDoktors
alter InkarnationDesDoktors add schauspieler Schauspieler;
alter InkarnationDesDoktors add begleiter array[Begleiter];
Das Schema des Entity-Typs InkarnationDesDoktors aus Abbildung 20 wird
mit Durchführung dieser Update-Methoden, wie nachfolgend in Abbildung 24
beschrieben, geändert. Die Informationen zu dem Schauspieler werden nicht
redundant im Inkarnations-Entity gespeichert, sondern bei Bedarf automatisch
dereferenziert. Die aus Abbildung 22 bekannte Beispiel-Entity verändert sich nach
der Durchführung der Schema-Updates und entsprechender Datenmigration wie in
Abbildung 25 gezeigt.
{"$schema": "http://json-schema.org/draft-04/schema#,
"entityType": "InkarnationDesDoktors",
"schemaVersion": 2,
"acceptedSchemas": [2],
"usedSchemas": [1,2],
"useEagerMigration":true,
"type":"object",
"properties":{
"entityID": {"type":"integer"},
"validSchemaVersion": {"type":"integer"},
"aussehen":{"type":"string"},
"kleidung":{"type":"string"},
"episoden":{"type":"array","items":{"type":"string"}},
"schauspieler":{ "$ref":"#/schauspieler"}
},
"required":["entityID","validSchemaVersion", "schauspieler"]
}
Abbildung 24: JSON Schema-Definition des Entity-Typs InkarnationDesDoktors
nach der Durchführung von Schema-Updates
139
{
"entityType": "InkarnationDesDoktors",
"entityID": 10,
"validSchemaVersion":
2,
"aussehen":"braune Haare",
"kleidung":"brauner Anzug, Krawatte, Chucks",
"episoden":["14-60", "103"],
"schauspieler":{
"entityType": "Schauspieler",
"entityID": 5,
"validSchemaVersion":
"vorname":"David",
2,
"nachname":"Tennant"
}
}
-----------------{
"entityType": "Schauspieler",
"entityID": 5,
"validSchemaVersion":
2,
"vorname":"David",
"nachname":"Tennant"
}
Abbildung 25: Beispiel-Entity vom Typ InkarnationDesDoktors nach der
Durchführung von Schema-Updates
Datenmigration
Wie oben bereits erläutert, unterstützt die Schema-Management-Komponente
sowohl eager als auch lazy Migration. Die Strategie ist vom User für jeden EntityTyp separat wählbar.
Die Datenmigration soll automatisch vom Schema-Evolution-Manager aufgerufen
und entsprechend der konfigurierten Migrationsstrategie ausgeführt werden.
Hierzu müssen die erforderlichen Migrationsschritte aus den Schema-Änderungen
abgeleitet werden. Außerdem soll auch die umgekehrte Umsetzung integriert
140
werden. Werden Daten in die Datenbank geschrieben, die das Schema ändern,
sollen automatisch die entsprechenden Schema-Evolutions-Methoden ausgeführt
werden.
Schema-Extraktion
Für eine erste Version der Schema-Management-Komponente ist die Realisierung
des Schema-Extraction-Managers eher niedrig priorisiert. Daher wird dessen
Umsetzung hier nicht detaillierter beschrieben.
141
5
Fazit und Ausblick
5.1
Fazit
Ziel dieser Arbeit war es zunächst ausgewählte NoSQL-Datenbanksysteme
hinsichtlich ihrer Unterstützung des Schema-Managements zu analysieren. Zu
diesem Zweck wurde ein Anforderungskatalog erstellt, der sich u.a. an den
gängigen
Anforderungen
an
ein
Schema-Management
in
relationalen
Datenbanksystemen orientiert. Anhand dieser Kriterien wurde die Unterstützung
des Schema-Managements der wichtigsten sechs NoSQL-Datenbanksysteme
untersucht. Darüber hinaus wurden aktuelle Entwicklungen im Bereich des
Schema-Managements, ebenfalls mit Hilfe der zu Beginn definierten Kriterien,
betrachtet.
In den durchgeführten Analysen konnte festgestellt werden, dass sowohl die
untersuchten
NoSQL-Datenbanksysteme,
Entwicklungen
nur
eine
unzureichende
als
auch
Unterstützung
die
für
zusätzlichen
das
Schema-
Management zur Verfügung stellen.
Dennoch konnten einige Teilbereiche identifiziert werden, in denen die
Anforderungen relativ umfassend erfüllt werden. Mit Hilfe der zusätzlichen
Aufsätze lassen sich die Möglichkeiten der Schema-Modellierung deutlich
verbessern, sofern dies nicht ohnehin schon, wie z.B. von Cassandra, weitgehend
unterstützt wird. Als vielversprechendste Entwicklung kann KijiSchema diverse
weitere
Kriterien
erfüllen.
Nachteil
dieses
Frameworks
ist
jedoch
die
Beschränkung auf HBase als einziges unterstütztes NoSQL-Datenbanksystem.
Aus diesem Grund wurden die gewonnenen Erkenntnisse im weiteren Verlauf der
Arbeit genutzt, um eine Schema-Management-Komponente zu entwerfen. Diese
erfüllt neben den Analyse-Kriterien einige zusätzliche Anforderungen. So wurde
die Komponente von vornherein modular und systemunabhängig geplant, damit
eine größtmögliche Flexibilität gewährleistet werden kann. Die entworfene
Komponente verwendet, soweit möglich, Module der analysierten NoSQL142
Systeme bzw. der zusätzlichen Aufsätze nach einer entsprechenden Anpassung
wieder, um den Entwicklungsaufwand möglichst effizient zu gestalten.
Abschließend lässt sich festhalten, dass die Entwicklung im Bereich des SchemaManagements von NoSQL-Datenbanksystemen noch am Beginn steht. Es ist
weitere Forschungs- und Entwicklungsarbeit erforderlich, bevor sich erste
Lösungen etablieren und den Arbeitsalltag mit NoSQL-Systemen merklich
erleichtern.
5.2
Ausblick
Im Verlauf dieser Arbeit ist der Entwurf einer Schema-Management-Komponente
entstanden. Anhand eines fortlaufenden, sich weiterentwickelnden Beispiels wurde
gezeigt, dass die im Vorfeld definierten Anforderungen von dieser Komponente
erfüllt werden.
Als logische Fortführung bietet sich die prototypische Implementierung der
entworfenen Schema-Management-Komponente im Rahmen einer nachfolgenden
Master- oder Projektarbeit an.
Zusätzlich sind die offenen Fragen, wie beispielsweise die konkrete Umsetzung
der Schema-Extraktion, zu beantworten. Auch ist noch zu entscheiden, ob die
Realisierung
einer
Anfrage-
und
Schema-Evolutionssprache
durch
eine
vollständige Eigenentwicklung oder die Anpassung existierender Varianten
erfolgen
soll.
Dies
erfordert
etwas
tiefergehende
Analysen
und
Aufwandsabschätzungen, die im Zuge der oben erwähnten ImplementierungsMasterarbeit ebenfalls durchgeführt werden können.
143
6
Literatur
[Avr-14a]
Avro, Apache: Apache Avro 1.7.6 Documentation;
http://avro.apache.org/docs/current/index.html; 2014
[Avr-14b]
Avro, Apache: Apache Avro 1.7.6 Getting Started (Java);
http://avro.apache.org/docs/current/gettingstartedjava.html;
2014
[Avr-14c]
Avro, Apache: Apache Avro 1.7.6 Specification;
http://avro.apache.org/docs/current/spec.html#schemas; 2014
[Cas-12]
Datastax: Schema in Cassandra 1.1 : DataStax;
http://www.datastax.com/dev/blog/schema-in-cassandra-1-1;
2012
[Cas-13a]
Datastax: ColumnMetadata (DataStax Java Driver for Apache
Cassandra – Core 1.0.5 API);
http://www.datastax.com/drivers/java/1.0/com/datastax/driver/c
ore/ColumnMetadata.html; 2013
[Cas-13b]
Datastax: TableMetadata (DataStax Java Driver for Apache
Cassandra – Core 1.0.5 API);
http://www.datastax.com/drivers/java/1.0/com/datastax/driver/c
ore/TableMetadata.html; 2013
[Cas-13c]
Apache, JIRA, Cassandra: [Cassandra-1585] Support
renaming columnfamilies and keyspaces – ASF JIRA;
https://issues.apache.org/jira/browse/CASSANDRA-1585;
2013
[Cas-14a]
Datastax: Getting Started;
http://www.datastax.com/documentation/gettingstarted/index.h
tml?
pagename=docs&version=quick_start&file=quickstart#getting_
started/gettingStarteddataModel_c.html; 2014
[CDB-14a]
CouchDB, Apache: 1.5 The Core API – Apache CouchDB 1.6
Documentation;
http://docs.couchdb.org/en/latest/intro/api.html, 2014
144
[CDB-14b]
CouchDB, Apache: 1.1 Technical Overview – Apache
CouchDB 1.6 Documentation;
http://docs.couchdb.org/en/latest/intro/overview.html, 2014
[CDB-14c]
CouchDB, Apache: 3.10 HTTP Resource Handlers – Apache
CouchDB 1.6 Documentation;
http://docs.couchdb.org/en/latest/config/http-handlers.html;
2014
[CDB-14d]
CouchDB, Apache: 10.2.1 / - Apache CouchDB 1.6
Documentation;
http://docs.couchdb.org/en/latest/api/server/common.html#alldbs; 2014
[CDB-14e]
CouchDB, Apache: 10.3.2 /db/_all_docs – Apache CouchDB
1.6 Documentation;
http://docs.couchdb.org/en/latest/api/database/bulk-api.html;
2014
[CDB-14f]
CouchDB, Apache: 10.3.1 /db – Apache CouchDB 1.6
Documentation;
http://docs.couchdb.org/en/latest/api/database/common.html;
2014
[CDB-14g]
CouchDB, Apache: 10.4.1 /db/doc – Apache CouchDB 1.6
Documentation;
http://docs.couchdb.org/en/latest/api/document/common.html;
2014
[CDB-14h]
CouchDB, Apache: 10.5.1 /db/_design/design-doc – Apache
CouchDB 1.6 Documentation;
http://docs.couchdb.org/en/latest/api/ddoc/common.html; 2014
[CDB-14i]
CouchDB, Apache: 6.1 Design Functions – Apache CouchDB
1.6 Documentation;
http://docs.couchdb.org/en/latest/couchapp/ddocs.html; 2014
[CDB-13a]
CouchDB: HTTP_Document_API – Couchdb Wiki;
http://wiki.apache.org/couchdb/HTTP_Document_API; 2013
[CDB-11a]
CouchDB: EntityRelationship – Couchdb Wiki;
http://wiki.apache.org/couchdb/EntityRelationship; 2011
145
[CDB-11b]
CouchDB: Document_revisions – Couchdb Wiki;
http://wiki.apache.org/couchdb/Document_revisions?
action=show&redirect=DocumentRevisions; 2011
[Cou-13a]
Couchbase: Couchbase and Apache CouchDB,
http://www.couchbase.com/couchbase-vs-couchdb, 2013
[Cou-13b]
Couchbase: Couchbase Manual 2.2 – Introduction to
Couchbase Server, http://docs.couchbase.com/couchbasemanual-2.2/#introduction-to-couchbase-server, 2013
[Cou-13c]
Couchbase: Couchbase Devguide 2.2 – Introduction to
Couchbase, http://docs.couchbase.com/couchbase-devguide2.2/#introduction-to-couchbase, 2013
[Cou-13d]
Couchbase: Couchbase Devguide 2.2 – Storing Data;
http://docs.couchbase.com/couchbase-devguide-2.2/#storingdata; 2013
[Cou-13e]
Couchbase: Couchbase Manual 2.2 – Using the REST Api;
http://docs.couchbase.com/couchbase-manual-2.2/#using-therest-api; 2013
[Cou-13f]
Couchbase: Coucbase Manual 2.2 – Views and Indexes;
http://docs.couchbase.com/couchbase-manual-2.2/#viewsand-indexes; 2013
[Cou-13g]
Couchbase: Couchbase Manual 2.2 – Using the Web
Console; http://docs.couchbase.com/couchbase-manual2.2/#using-the-web-console; 2013
[Cou-13h]
Couchbase: Couchbase Devguide 2.2 – Modeling Documents;
http://docs.couchbase.com/couchbase-devguide2.2/#modeling-documents; 2013
[Cou-13i]
Couchbase: Couchbase Devguide 2.2 – Finding Data with
Views; http://docs.couchbase.com/couchbase-devguide2.2/#finding-data-with-views; 2013
[Cou-13j]
Couchbase: Couchbase Java SDK 1.3 – Developer Guide;
http://docs.couchbase.com/couchbase-sdk-java-1.3/; 2013
146
[Cou-13k]
Couchbase: CouchbaseClient (couchbase-client 1.3.0 API);
http://www.couchbase.com/autodocs/couchbase-java-client1.3.0/index.html; 2013
[CQL-13a]
Cassandra, Apache: CQL v3.1.2 – Data Definition;
http://cassandra.apache.org/doc/cql3/CQL.html#dataDefinition
, 2013
[CQL-13b]
Cassandra, Apache: CQL v3.1.2 – Data Manipulation;
http://cassandra.apache.org/doc/cql3/CQL.html#dataManipulat
ion; 2013
[CQL-14a]
Datastax: CQL for Cassandra 2.0 – Datastax CQL 3.1
Documentation - Glossary;
http://www.datastax.com/documentation/cql/3.1/webhelp/index
.html#cassandra/glossary/gloss_glossary.html; 2014
[CQL-14b]
Datastax: CQL for Cassandra 2.0 – Datastax CQL 3.1
Documentation – Data modeling example;
http://www.datastax.com/documentation/cql/3.1/webhelp/index
.html#cql/ddl/ddl_intro_c.html; 2014
[CQL-14c]
Datastax: CQL for Cassandra 2.0 – Datastax CQL 3.1
Documentation – Querying a system
table;http://www.datastax.com/documentation/cql/3.1/webhelp/
index.html#cql/cql_using/use_query_system_c.html ; 2014
[EFH-11]
Edlich, S.; Friedland, A.; Hampe, J.; Brauer, B.; Brückner, M.:
NoSQL: Einstieg in die Welt nichtrelationaler WEB2.0
Datenbanken; 2. Auflage; München: Carl Hanser Verlag, 2011
[EN-05]
Elmasri, Ramez; Navathe, Shamkant B.: Grundlagen von
Datenbanksystemen – Ausgabe Grundstudium; 3. Auflage;
München: Pearson Studium, 2005
[GAE-12]
Google Developers: Updating Your Model's Schema – Google
App Engine – Google Developers;
https://developers.google.com/appengine/articles/update_sch
ema; 2012
147
[GAE-13a]
Google Developers: What is Google App Engine? - Google
App Engine – Google Developers;
https://developers.google.com/appengine/docs/whatisgooglea
ppengine; 2013
[GAE-13b]
Google Developers: Data Modeling in Python – Google App
Engine – Google Developers;
https://developers.google.com/appengine/docs/python/datasto
re/datamodeling; 2013
[GAE-13c]
Google Developers: Google App Engine – Google Developers
– Datastore Indexes;
https://developers.google.com/appengine/docs/python/datasto
re/indexes; 2013
[GAE-13d]
Google Developers: Google App Engine – Google Developers
– Metadata;
https://developers.google.com/appengine/docs/python/datasto
re/metadataqueries; 2013
[GAE-13e]
Google Developers: The Property Class – Google App Engine
– Google Developers;
https://developers.google.com/appengine/docs/python/datasto
re/propertyclass; 2013
[GAE-13f]
Google Developers: The Model Class – Google App Engine –
Google Developers;
https://developers.google.com/appengine/docs/python/datasto
re/modelclass; 2013
[GAE-14a]
Google Developers: Google App Engine – Google Developers
– Java Datastore API;
https://developers.google.com/appengine/docs/java/datastore;
2013
[GAE-14b]
Google Developers: Google App Engine – Google Developers
– Entities, Properties, and Keys- Java;
https://developers.google.com/appengine/docs/java/datastore/
entities; 2014
148
[GAE-14c]
Google Developers: Google App Engine – Google Developers
– Entities, Properties, and Keys- Python;
https://developers.google.com/appengine/docs/python/datasto
re/entities; 2014
[HBa-13a]
HBase, Apache: The Apache HBase Reference Guide. ,
2013http://hbase.apache.org/book/book.html
[HBa-13b]
HBase, Apache: The Apache HBase Reference Guide:
Chapter 5. Data Model.
http://hbase.apache.org/book.html#datamodel, 2013
[HBa-13c]
HBase, Apache: The Apache HBase Reference Guide:
Chapter 6. HBase and Schema Design.
http://hbase.apache.org/book.html#schema, 2013
[HBa-13d]
HBase, Apache: The Apache HBase Reference Guide:
Chapter 2.3. Configuration Files.
http://hbase.apache.org/book/config.files.html, 2013
[HBa-13e]
HBase, Apache: HTableDescriptor (HBase 0.9.0-SNAPSHOT
API);
http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/H
TableDescriptor.html; 2013
[HBa-13f]
HBase, Apache: HBaseAdmin (HBase 0.97.9-SNAPSHOT
API);
http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/cli
ent/HBaseAdmin.html; 2013
[HBa-13g]
HBase, Apache: Constraint (HBase 0.9.7-SNAPSHOT API);
http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/co
nstraint/Constraint.html; 2013
[HBa-13h]
HBase, Apache: HColumnDescriptor (HBase 0.9.0SNAPSHOT API);
http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/H
ColumnDescriptor.html; 2013
[HBa-13i]
HBase, Apache: Put (HBase 0.9.0-SNAPSHOT API);
http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/cli
ent/Put.html; 2013
149
[HBa-13j]
HBase, Apache: The Apache HBase Reference Guide:
Chapter 15. Apache HBase Operational Management;
http://hbase.apache.org/book.html#ops_mgt, 2013
[Jiq-13]
JSONiq: JSONiq Use Cases;
http://www.jsoniq.org/docs/JSONiq-usecases/htmlsingle/index.html; 2013
[Jiq-14]
JSONiq: JSONiq – The JSON Query Language;
http://www.jsoniq.org; 2014
[JSc-12]
IETF, JSON Schema: JSON Reference;
http://tools.ietf.org/id/draft-pbryan-zyp-json-ref-03.html; 2012
[JSc-13a]
IETF, JSON Schema: JSON Schema: core definitions and
terminology; http://json-schema.org/latest/json-schemacore.html; 2013
[JSc-13b]
IETF, JSON Schema: JSON Schema: interactive and non
interactive validation; http://json-schema.org/latest/jsonschema-validation.html; 2013
[JSc-13c]
Droettboom, Michael: The basics – Understanding JSON
Schema 1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/basics.html; 2013
[JSc-13d]
Droettboom, Michael: Type-specific keywords –
Understanding JSON Schema 1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/reference/type.html#type; 2013
[JSc-13e]
Droettboom, Michael: string – Understanding JSON Schema
1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/reference/string.html; 2013
[JSc-13f]
Droettboom, Michael: Numeric types – Understanding JSON
Schema 1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/reference/numeric.html; 2013
150
[JSc-13g]
Droettboom, Michael: array – Understanding JSON Schema
1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/reference/array.html; 2013
[JSc-13h]
Droettboom, Michael: object – Understanding JSON Schema
1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/reference/object.html; 2013
[JSc-13i]
Droettboom, Michael: Generic keywords – Understanding
JSON Schema 1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/reference/generic.html, 2013
[JSc-13j]
Droettboom, Michael: Combining schemas – Understanding
JSON Schema 1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/reference/combining.html; 2013
[JSc-13k]
Droettboom, Michael: Structuring a complex schema –
Understanding JSON Schema 1.0 documentation;
http://spacetelescope.github.io/understanding-jsonschema/structuring.html; 2013
[JSc-14a]
JSON Schema: JSON Schema and Hyper-Schema;
http://json-schema.org; 2014
[JSc-14b]
JSON Schema: JSON Schema Software; http://jsonschema.org/implementations.html; 2014
[JSc-14c]
JSON Schema: JSON Schema – Documentation; http://jsonschema.org/documentation.html; 2014
[JSO-14]
JSON: Introducing JSON; http://json.org; 2014
[Kij-13]
KijiProject, Apache: Kiji-schema /
TableLayoutUpdateValidator.java – GitHub;
https://github.com/kijiproject/kiji-schema/blob/master/kijischema/src/main/java/org/kiji/schema/layout/impl/TableLayout
UpdateValidator.java; 2013
151
[Kij-14a]
KijiProject, Apache: Kiji Community – Build Real-Time
Scalable Data Applications on Apache HBase;
http://www.kiji.org; 2014
[Kij-14b]
KijiProject, Apache: Architecture | Kiji Community – Build
Real-Time Scalable Data Applications on Apache HBase;
http://www.kiji.org/architecture; 2014
[Kij-14c]
KijiSchema, Apache: Data Model;
http://docs.kiji.org/userguides/schema/1.3.2/data-model/; 2014
[Kij-14d]
KijiProject, Apache: Get Started | Kiji Community – Build RealTime Scalable Data Applications on Apache HBase;
http://www.kiji.org/getstarted/; 2014
[Kij-14e]
KijiSchema, Apache: Managing Data;
http://docs.kiji.org/userguides/schema/1.3.2/managing-data/;
2014
[Kij-14f]
KijiSchema, Apache: DDL Shell Reference;
http://docs.kiji.org/userguides/schema/1.3.2/schema-shell-ddlref/; 2014
[Kij-14g]
KijiProject: Arch: KijiSchema – kijiproject/wiki Wiki – GitHub;
https://github.com/kijiproject/wiki/wiki/Arch%3A-KijiSchema;
2014
[Kij-14h]
KijiProject, Apache: Features | Kiji Community – Build RealTime Scalable Data Apllications on Apache HBase;
http://www.kiji.org/features; 2014
[Kij-14i]
KijiSchema, Apache: Overview (kiji-schema 1.3.6 API);
http://api-docs.kiji.org/kiji-schema/1.3.6/index.html: 2014
[KSS-14]
Klettke, M.; Scherzinger, S.; Störl, U.: Datenbanken ohne
Schema? - Herausforderungen und Lösungs-Strategien in der
agilen Anwendungsentwicklung mit schema-flexiblen NoSQLDatenbanksystemen;
Datenbank-Spektrum,
Volume
14,
Nummer 2, Juli 2014.2014
[Kun-14a]
Kundera: Home – impetus-opensource/Kundera Wiki –
GitHub; https://github.com/impetus-opensource/Kundera/wiki;
2014
152
[Kun-14b]
Kundera: Datastores Supported – impetusopensource/Kundera Wiki – GitHub;
https://github.com/impetusopensource/Kundera/wiki/Datastores-Supported; 2014
[Kun-14c]
Kundera: Architecture – impetus-opensource/Kundera Wiki –
GitHub; https://github.com/impetusopensource/Kundera/wiki/Architecture; 2014
[Kun-14d]
Kundera: Concepts – impetus-opensource/Kundera Wiki –
GitHub; https://github.com/impetusopensource/Kundera/wiki/Concepts; 2014
[Kun-14e]
Kundera: Polyglot Persistence – impetus-opensource/Kundera
Wiki – GitHub; https://github.com/impetusopensource/Kundera/wiki/Polyglot-Persistence; 2014
[Kun-14f]
Kundera: JPQL – impetus-opensource/Kundera Wiki –
GitHub; https://github.com/impetusopensource/Kundera/wiki/JPQL; 2014
[Kun-14g]
Kundera: Schema Generation – impetus-opensource/Kundera
Wiki – GitHub; https://github.com/impetusopensource/Kundera/wiki/Schema-Generation; 2014
[Kun-14h]
Kundera: Using Compound keys with Kundera – impetusopensource/Kundera Wiki – GitHub;
https://github.com/impetus-opensource/Kundera/wiki/UsingCompound-keys-with-Kundera; 2014
[Kun-14i]
Kundera: Mapped SuperClass Support – impetusopensource/Kundera Wiki – GitHub;
https://github.com/impetus-opensource/Kundera/wiki/MappedSuperClass-Support; 2014
[Kun-14j]
Kundera: Object to NoSQL Data mapping – impetusopensource/Kundera Wiki – GitHub;
https://github.com/impetus-opensource/Kundera/wiki/Objectto-NoSQl-Data-mapping; 2014
153
[Kun-14k]
Kundera: Secondary Index Mapping – impetusopensource/Kundera Wiki – GitHub;
https://github.com/impetusopensource/Kundera/wiki/Secondary-Index-Mapping-inCassandra; 2014
[Kun-14l]
Kundera: Native CQL3 to object mapping – impetusopensource/Kundera Wiki – GitHub;
https://github.com/impetus-opensource/Kundera/wiki/NativeCQL3-to-object-mapping; 2014
[Leo-13]
Leonard, Anghel: Pro Hibernate and MongoDB – Expert's
Voice in Java and MongoDB; Apress 2013
[Mgo-11]
Mongoose: Mongoose ODM v3.8.6; http://mongoosejs.com;
2011
[Mgo-14a]
Mongoose: Mongoose Schemas v3.8.6;
http://mongoosejs.com/docs/guide.html; 2014
[Mgo-14b]
Mongoose: Mongoose Models v3.8.6;
http://mongoosejs.com/docs/models.html; 2014
[Mgo-14c]
Mongoose: Mongoose Documents v3.8.6;
http://mongoosejs.com/docs/documents.html; 2014
[Mgo-14d]
Mongoose: Mongoose SubDocuments v3.8.6;
http://mongoosejs.com/docs/subdocs.html; 2014
[Mgo-14e]
Mongoose: Mongoose Validation v3.8.6;
http://mongoosejs.com/docs/validation.html; 2014
[Mgo-14f]
Mongoose: Mongoose Queries v3.8.6;
http://mongoosejs.com/docs/queries.html; 2014
[Mgo-14g]
Mongoose: Mongoose Query Population v3.8.6;
http://mongoosejs.com/docs/populate.html; 2014
[Mgo-14h]
Mongoose: Mongoose API v3.8.6 – schematype.js;
http://mongoosejs.com/docs/api.html#schematype-js; 2014
[Mon-13a]
MongoDB: Documents – MongoDB Manual 2.4.8;
http://docs.mongodb.org/manual/core/document/, 2013
[Mon-13b]
MongoDB: Write Operations – MongoDB Manual 2.4.8;
http://docs.mongodb.org/manual/core/write-operations/, 2013
154
[Mon-13c]
MongoDB: Database References – MongoDB Manual 2.4.8;
http://docs.mongodb.org/manual/reference/databasereferences/, 2013
[Mon-13d]
MongoDB: Capped Collections – MongoDB Manual 2.4.8;
http://docs.mongodb.org/manual/core/capped-collections/,
2013
[Mon-13e]
MongoDB: Data Modeling Introduction – MongoDB Manual
2.4.8; http://docs.mongodb.org/manual/core/data-modelingintroduction/, 2013
[Mon-13f]
MongoDB: System Collections – MongoDB Manual 2.4.8;
http://docs.mongodb.org/manual/reference/systemcollections/; 2013
[Mon-13g]
MongoDB: Unique Indexes – MongoDB Manual 2.4.8;
http://docs.mongodb.org/manual/core/index-unique/; 2013
[Mon-13h]
MongoDB: MongoClient;
http://api.mongodb.org/java/current/com/mongodb/MongoClie
nt.html; 2013
[Mon-13i]
MongoDB: DB;
http://api.mongodb.org/java/current/com/mongodb/DB.html;
2013
[Mon-13j]
MongoDB: DBCollection;
http://api.mongodb.org/java/current/com/mongodb/DBCollectio
n.html; 2013
[Mon-13k]
MongoDB: Getting Started with Java Driver;
http://docs.mongodb.org/ecosystem/tutorial/getting-startedwith-java-driver/; 2013
[Mon-13l]
MongoDB: Configuration File Options – MongoDB Manual
2.4.8;
http://docs.mongodb.org/manual/reference/configurationoptions/#objcheck; 2013
[Mon-13m]
MongoDB: db.collection.copyTo() - MongoDB Manual 2.4.8;
http://docs.mongodb.org/manual/reference/method/db.collectio
n.copyTo/, 2013
155
[Mon-13n]
MongoDB, JIRA: [Server-701] Ability to rename databases –
MongoDB; https://jira.mongodb.org/browse/SERVER-701;
2013
[Njs-14]
Joyent: node.js; http://nodejs.org; 2014
[OAE-12a]
Google: LifecycleCallbacks – objectify-appengine;
https://code.google.com/p/objectifyappengine/wiki/LifecycleCallbacks; 2012
[OAE-12b]
Google: SchemaMigration – objectify-appengine;
https://code.google.com/p/objectifyappengine/wiki/SchemaMigration; 2012
[OAE-13a]
Google: Introduction – objectify-appengine;
https://code.google.com/p/objectifyappengine/wiki/Introduction ;2013
[OAE-13b]
Google: Entities – objectify-appengine;
https://code.google.com/p/objectify-appengine/wiki/Entities;
2013
[OAE-13c]
Google: Concepts – objectify-appengine;
https://code.google.com/p/objectify-appengine/wiki/Concepts?
tm=6 ; 2013
[OAE-14a]
Google: objectify-appengine;
https://code.google.com/p/objectify-appengine/ ; 2014
[OAE-14b]
Google: Queries – objectify-appengine;
https://code.google.com/p/objectify-appengine/wiki/Queries;
2014
[OGM-13a]
JBoss, Hibernate OGM: Preface;
http://docs.jboss.org/hibernate/ogm/4.0/reference/enUS/html/preface.html; 2013
[OGM-13b]
JBoss, Hibernate OGM: Chapter 3. Architecture;
http://docs.jboss.org/hibernate/ogm/4.0/reference/enUS/html/ogm-architecture.html; 2013
[OGM-13c]
JBoss, Hibernate OGM: Chapter 5. Datastores;
http://docs.jboss.org/hibernate/ogm/4.0/reference/enUS/html/ogm-datastore-providers.html; 2013
156
[OGM-13d]
JBoss, Hibernate OGM: Chapter 6. Map your entities;
http://docs.jboss.org/hibernate/ogm/4.0/reference/enUS/html/ogm-mapping.html; 2013
[OGM-13e]
JBoss, Hibernate OGM: Chapter 7. Query your entities;
http://docs.jboss.org/hibernate/ogm/4.0/reference/enUS/html/ogm-query.html; 2013
[OGM-14a]
JBoss, Hibernate OGM: Hibernate OGM – Hibernate OGM;
http://hibernate.org/ogm/; 2014
[OGM-14b]
JBoss, Hibernate OGM: Hibernate OGM documentation –
Hibernate OGM; http://hibernate.org/ogm/documentation/;
2014
[OGM-14c]
JBoss, Hibernate OGM: Getting started with Hibernate OGM –
Hibernate OGM;
http://hibernate.org/ogm/documentation/getting-started/; 2014
[OGM-14d]
JBoss, Hibernate OGM: Hibernate OGM roadmap – Hibernate
OGM; http://hibernate.org/ogm/roadmap/#hibernate-ogm-next;
2014
[RFC-4627]
RFC 4627 – The application/ json Media Type for JavaScript
Object Notation (JSON); http://tools.ietf.org/html/rfc4627, 2006
[RW-12]
Redmond, E.; Wilson, J.R.: Seven Databases in Seven
Weeks: A Guide to Modern Databases and the NoSQL
Movement; Pragmatic Programmers, 2012
[SKS-13]
Scherzinger, S.; Klettke, M.; Störl, U.: Managing Schema
Evolution in NoSQL Data Stores; In: Proc. DBPL; 2013
[Sta-11]
Stackoverflow: Refactoring a Google App Engine Datastore;
http://stackoverflow.com/questions/6473538/refactoring-agoogle-app-engine-datastore; 2011
[Sta-12]
Stackoverflow: How to rename a CouchDB database?;
http://stackoverflow.com/questions/11589186/how-to-renamea-couchdb-database; 2012
[Sta-13]
Stackoverflow: Hbase Schema Nested Entity;
http://stackoverflow.com/questions/14511708/hbase-schemanested-entity, 2013
157
[Tiw-11]
Tiwari, Shashank: Professional NoSQL; Indianapolis, Indiana:
John Wiley & Sons; 2011
158
Herunterladen