Viele, die schon einmal eine Webseite programmiert haben, hatten sicher schon mit MySQL zu tun. MySQL ist eine sogenannte relationale Datenbank. In solchen Datenbanken werden Daten in Tabellen gespeichert. Das erste, was man als Programmierer tun muss, ist die Definition der Tabellen. Man muss entscheiden, welche Information in welche Spalte kommt und welche Informationen in eine getrennte Tabelle sollen. Den Vorgang nennt man Normalisierung. An dieser Normalisierung beißt man sich schon mal die Zähne aus. Macht man hier Fehler, ist es später häufig schwierig, neue Daten hinzuzufügen. Übertreibt man die Normalisierung, kann das zu komplexen Abfragen und schlechter Performance führen. Auch die Abfragen sind manchmal eine Wissenschaft für sich.
NoSQL
Seit einigen Jahren gibt es eine andere Art von Datenbanken, die sogenannten NoSQL Datenbanken. NoSQL ist eigentlich nicht der richtige Begriff. Gemeint sind Datenbanken, für die man keine SQL Anweisungen benötigt. Genau betrachtet wäre zum Beispiel XML auch NoSQL, da die gespeicherten Daten hier ebenfalls ohne SQL Befehle bearbeitet werden können. Aber das sind Spitzfindigkeiten. Was mit NoSQL eigentlich gemeint ist sind…
Dokumentorientierte Datenbanken
Bei einer dokumentorientierten Datenbank gibt es keine Tabellen. Ein Datensatz in einer dokumentorientierten Datenbank hat kein festes Schema, das bestimmt, welche Information an welcher Stelle steht. Es gibt auch keine richtige Normalisierung wie bei relationalen Datenbanken. Man versucht im Gegensatz dazu möglichst alle zusammengehörende Daten in einen Datensatz zu speichern.
Möchte man zum Beispiel ein Adressbuch erstellen, würde man bei einer relationalen Datenbank als erstes eine Tabelle erstellen, in der alle einzigartigen Daten untergebracht werden, zum Beispiel Vorname, Nachname, Geburtsdatum usw. Würde man in dieser Tabelle auch die Adresse speichern, könnte man für jeden Kontakt im Adressbuch nur eine Adresse anlegen. Also legt man eine zweite Tabelle an mit Feldern wie Straße, Postleitzahl und Ort. Außerdem benötigt man noch ein Feld, in dem ein Verweis auf den eigentlichen Kontakt gespeichert wird, damit man später die Informationen zusammenfügen kann.
Ein Kontakt benötigt aber nicht nur eine Adresse sondern auch andere Kontaktdaten wie eine Telefonnummer oder eine Email Adresse. Und hier geht es schon los. Wo und wie speichert man diese Daten ab? Einige erstellen eine eigene Tabelle, andere fügen der Adresstabelle einfach Felder für 1-2 Telefone, Fax und Email hinzu. Und was macht man mit weiteren Kontaktdaten wie IDs von Jabber, ICQ oder GoogleTalk? Auch an die Adresstabelle anhängen? Zusammen mit Telefon und Email in eine Tabelle? Eine eigene Tabelle? Gebt diese Aufgabe fünf Datenbankentwicklern und ihr bekommt fünf verschiedene Lösungen.
Eine dokumentorientierte Datenbank speichert sämtliche Kontaktdaten in einem Dokument. Das Dokument wird als Dictionary, also ein assoziatives Array, gespeichert. Ein assoziatives Array besteht aus einer Reihe von Schlüssel/Wert Paaren. Der Schlüssel gibt an, worum es sich bei dem Wert handelt. Im Fall der Adressdatenbank also zum Beispiel ‘Vorname’ oder ‘Geburtsdatum’.
Wenn ich vorher gesagt habe, dass es kein Schema gibt ist daher allerdings nur die halbe Wahrheit. Für das Dokument selbst sollte man sich schon ein halbwegs sinnvolles Schema einfallen lassen, damit man die Daten später auch wieder sinnvoll abrufen kann. Schemafrei bedeutet in erster Linie, dass die Datenbank kein festes Schema fordert. Vielmehr kann in jedem Datensatz einer Datenbank ein anderes Dokument abgespeichert werden.
Eine relationale Datenbank verwendet Tabellen. Jeder Spalte in dieser Tabelle wird eine bestimmte Funktion und ein bestimmter Datentyp zugeordnet. Eine Spalte soll den Vornamen speichern und kann daher Texte speichern. Eine andere Spalte soll das Geburtsdatum enthalten und hat deshalb meist den Typ “Date”.
Eine dokumentorientierte Datenbank kann man sich als lange Reihe von Zetteln vorstellen und auf jeden dieser Zettel kann man schreiben was man will. Auf dem ersten Zettel steht eine Adresse, auf dem zweiten eine weitere, auf dem dritten kann aber zum Beispiel ein Kochrezept stehen usw. Schemafrei kann aber auch bedeuten, dass man Felder weglassen oder hinzufügen kann. Hat eine Person keinen Zweitnamen muss das Feld nicht vorhanden sein. Möchte man einer Person einen Geburtsnamen hinzufügen tut man dies einfach. Der Datenbank ist das egal. Sie speichert, was man ihr zum speichern übergibt. Es ist lediglich Sache des Programms, diese Daten korrekt zu verarbeiten und anzuzeigen. Bei relationalen Datenbanken müsste man für jede Eventualität eine Spalte zur Verfügung stellen und hat unter Umständen jede Menge leere Felder. Oder man legt eine universelle Spalte an und versucht da zusätzliche Informationen abzulegen, was aber meistens unnötig umständlich ist.
Eine dokumentorientierte Datenbank ist jedoch auch kein Allheilmittel und will kein Ersatz für relationale Datenbanken sein. Vielmehr haben beide Arten ihre Stärken und Schwächen. Wenn man eine Anwendung erstellt sollte man also überlegen, welche der Datenbankarten sich besser eignet. Unter Umständen ist sogar eine Kombination als beiden sinnvoll.
CouchDB
Ich habe mir CouchDB als Vertreter der objektorientieren Datenbanken herausgepickt. CouchDB ist mittlerweile ein Projekt bei der Apache Foundation und hat den selben Status wie der Apache Server oder Tomcat. CouchDB ist in Erlang programmiert und verwendet JSON zur Speicherung von Dokumenten und für die Übergabe der Daten. Abfragen werde in JavaScript durchgeführt und die Kommunikation erfolgt, wie zwischen einen Browser und einem Webserver, über das HTTP Protokoll.
So, genug Buzzwords. Gehen wir etwas mehr ins Detail. Wie die Buzzword Parade schon zeigt verwendet CouchDB viele Web Technologien. Genauer gesagt ist CouchDB ein Webserver. Das kann man ganz leicht mit CURL testen. Da CURL nicht zur Standard Installation von Ubuntu gehört muss man es installieren.
sudo apt-get install curl
Auf die gleiche Weise wird auch CouchDB installiert. Man kann mit CURL anschließend testen, ob CouchDB richtig installiert ist.
curl http://127.0.0.1:5984
{"couchdb":"Welcome","version":"1.0.1"}
So sollte das Ergebnis bei Maverick Meerkat aussehen. Wie man sieht liefert CouchDB als Antwort ein Dictionary im JSON Format. Vor dem Doppelpunkt steht jeweils der Schlüssel, in diesem Fall “couchdb” und “version”, hinter dem Doppelpunkt steht der Wert. Dictionaries werden in geschweifte Klammern gefasst und die einzelnen Schlüssel/Wert Paare mit Kommas getrennt. Man kann die Adresse http://127.0.0.1:5984 auch in die Adresszeile des Browsers eingeben. Man erhält das gleiche Ergebnis.
curl -X GET http://127.0.0.1:5984/_all_dbs
Mit diesem Befehl kann man abfragen, welche Datenbanken auf einem Server vorhanden sind. Unter Ubuntu sollte das bei einer frischen Installation so aussehen.
["_users"]
Wie man sieht ein ganz normaler GET Request. Dadurch ist es mit CouchDB nicht nur möglich, einfach Daten zu speichern, sondern man kann mit CouchDB und etwas JavaScript komplette Webseiten hosten, ganz ohne Apache oder PHP. Das ist in CouchDB: The Definite Guide anhand eines Blogs beschrieben. Aber natürlich kann man CouchDB auch als normalen Datenbankserver mit Python, Ruby oder PHP nutzen.
Im Titel schrieb ich “Eine Datenbank für Programmierer”. Warum? Bei relationalen Datenbanken werden die Daten in der Structured Query Language, kurz SQL, bearbeitet. Das ist eine eigene Sprache mit einer für Programmierer eigenwilligen Syntax.
CouchDB geht einen anderen Weg. Für Abfragen werden sogenannte Views (zu deutsch etwa “Ansichten”) verwendet. Diese Views werden wie normale Dokumente in der Datenbank gespeichert und können auch so abgerufen werden. Diese Views werden nicht in einer eigenen Sprache programmiert sondern verwenden standardmäßig JavaScript. Es ist jedoch auch möglich, die Views in anderen Sprachen wie Python zu implementieren. Diese Views nutzen für die Datenbearbeitung Map und Reduce, zwei Funktionen, die vielen Programmierern bekannt sein dürften.
MapReduce, JavaScript, bzw wahlweise eine andere Sprache, und Dictionaries sind alles Dinge, die man als Programmierer meistens schon kennt. Es sollte daher für einen geübten Programmierer einfacher sein, mit CouchDB zu arbeiten als mit einer relationalen SQL Datenbank, selbst in Verbindung mit einem ORM.
Ein weiterer Vorteil von CouchDB ist die einfache Möglichkeit der Replikation. Replikation bedeutet das Kopieren von einer Datenbank in eine andere. Es ist dabei egal, ob die Datenbank auf dem gleichen Server liegt oder auf einem entfernten. Die Vorgehensweise bleibt gleich. So lassen sich einfach und schnell Backups erstellen oder Daten kontinuierlich zwischen mehreren Rechnern synchronisieren. So kann man entweder große Datenbankcluster aufbauen, um die Performance zu steigern oder mit immer identischen Daten auf verschiedenen Rechnern arbeiten.
Eine wesentliche Schwäche von CouchDB soll aber auch nicht verschwiegen werden. Es ist in CouchDB nicht möglich, eine Volltextsuche oder partielle Suchen wie SELECT * FROM narf WHERE pui LIKE “%zort%” durchzuführen. Dafür ist eine zusätzliche Software wie Lucene notwendig. Lucene wird in CouchDB eingebunden und indexiert alle Texte. Damit ist dann eine Volltextsuche oder partielle Selects möglich.
Abschließend sei noch erwähnt, dass Ubuntu One mit CouchDB arbeitet. Bei einer normalen Ubuntu Installation läuft bereits eine CouchDB Instanz, allerdings mit einer Erweiterung namens DesktopCouch. Darüber kann man zum Beispiel Firefox Bookmarks oder Adressen in Evolution auf mehreren Rechnern synchronisieren, was bis dato aber noch nicht einwandfrei funktioniert. Für Natty haben die Entwickler aber versprochen, dass es besser wird, was ich bei meinen Tests bisher auch bestätigen kann.