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