PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


NoSQL: Ein Einstieg mit MongoDB

with 8 comments

Ein Gastbeitrag von Florian Heinze, Gründer von vsChart.

Für alle die sich fragen, NoSQL – was ist das und wie geht das überhaupt, folgend ein praktischer Einstieg am Beispiel von MongoDB.

Zunächst, was bezeichnet genau NoSQL? Der Begriff ist etwas unglücklich. Denn es geht nicht um die Ablehnung der Abfragesprache SQL, sondern um die Befürwortung von Alternativen zu den dominierenden Relationalen Datenbanken.
Die zwei Kernelemente dieser Bewegung sind aus typischen Anforderungen für moderne Webanwendungen erwachsen: Vereinfachung der Datenhaltung für die Entwicklung und  verbesserte horizontale Skalierbarkeit im Betrieb.

Zur Praxis

Die Installation von MongoDB selber geht recht fix. Dazu holt man sich dann noch die mongo-Eweiterung für PHP per pecl install mongo und fügt extension=mongo.so in der php.ini dazu.

Das reicht schon um loszulegen:

<?php
// automatische Verbindung mit localhost:27017
$mongo = new Mongo();
// $blog ist ein MongoDB-Objekt (vergleichbar mit MySQL-Datenbank, wird automatisch angelegt)
$blog = $mongo->blog;
// $posts ist eine MongoCollection (vergleichbar mit SQL-Tabelle, wird automatisch angelegt)
$posts = $blog->posts;
// schreiben
$posts->insert(array(
    'slug' => 'foo-bar',
    'title' => 'Foo Bar',
    'body' => '<p>Bar foo foo bar …</p>',
    'date' => new MongoDate(),
    'tags' => array( 'footag', 'bartag', 'foobar'),
));

Die Datenbank und Collection (Tabelle im SQL-Sinne) werden zur Laufzeit automatisch erstellt. Da auch die Anmeldung an der Datenbank ohne Authentifizierung auskommt, ist bequemer weise kein vorheriger administrativer Zugriff auf die MongoDB nötig.

Vorteile von dokumentorientierten Datenbanken

Das direkte Speichern nativer Arrays wie im Beispiel ist natürlich überaus praktisch. Strukturen wie man sie oft sowieso schon im eigenen Code verwendet können mit geringen Manipulationen direkt abgespeichert werden. Joins über IDs oder komplizierte Zwischentabellen um m:n Beziehungen darzustellen, wie aus der SQL-Welt, fallen im Idealfall komplett weg (wie oben bei den ‘tags’).

Der schemalose Ansatz der dokumentenorientierten Datenbanken macht die Entwicklung flexibler denn das umständliche Anlegen neuer Felder oder Tabellen über Administrationswerkzeuge ist nicht mehr nötig. Das macht das Aufspielen neuer Versionen auf Live- oder andere Entwicklungsserver oft deutlich einfacher.

Zwei weitere oft genannte Argumente für NoSQL und somit auch MongoDB sind einfache horizontale Skalierbarkeit und Performancevorteile für viele Anwendungsfälle. Der Trumpf Skalierbarkeit lässt sich aber natürlich erst bei wirklich großen Projekten ausspielen.

Innere Umstellung aus SQL-Sicht

Allerdings muss man den eigenen Entwicklungsansatz auch auf diese neuen Datenmodelle einstellen. Denn z.B. die Performancegewinne bei MongoDB erreicht man zu einem Teil erst dadurch, dass man möglichst versucht ohne “Joins” auszukommen. Das bedeutet dann in der Praxis das man alle Seitendaten für unseren Blog-Post z.B. in einen einzigen Datenbank-Eintrag schreibt:

<?php
// erweitern des obig angelegten Dokumentes
$posts->update(
    array( 'slug' => 'foo-bar'), // quasi eine where-Bedingung
    array( '$set' => array( // ohne set $set würde es den ganzen Post ersetzen
        'user' => array(
            'name' => 'Mr. Foo',
            'nick' => 'mrfoo',
        ),
        'comments' => array(
            0 => array(
                'date' => new MongoDate(),
                'name' => 'Ms Comment',
                'mail' => 'ms.comment@example.com',
                'text' => 'Bar foo bar …',
            ),
            1 => array(
                'date' => new MongoDate(),
                'name' => 'Mr Comment',
                'mail' => 'mr.comment@example.com',
                'text' => 'Foo bar foo …',
            ),
        ),
    ))
);
?>

Einiges davon wirkt natürlich nach vielen Jahren SQL-Erfahrung etwas unsauber. Erfahrungen zeigen aber das viele der Einsprüche für die Praxis nicht viel Bedeutung haben.
Der erste und vielleicht auch wichtigste Schritt im Umstieg zu NoSQL-Modellen ist es, den gewohnten Join-Ansatz aus den eigenen Gedanken so weit wie möglich zu verbannen.

Daten abfragen

Die Where-Bedingungen von Abfragen werden ebenfalls als Arrays übergeben. Einfache Abfragen sind so noch recht übersichtlich, aber bei komplexeren Statements geht dadurch manchmal die Orientierung verloren.

Um unser Beispiel abzuschließen, hier eine Abfrage plus vereinfachte Ausgabe:

<?php
$doc = $posts->findOne( array( 'slug' => 'foo-bar'));
echo '<h1>'.$doc['title'].'</h1>';
echo '<em>'.$doc['user']['name'].'/'.date('r', $doc['date']->sec).'</em>';
echo $doc['body'];
echo '<ul>';
foreach( $doc['comments'] as $key => $comment) {
    echo '<li>'.$comment['name'].': '.$comment['text'].'</li>';
}
echo '</ul>';
?>

Vorteile von MongoDB

Weitere Vorteile speziell von MongoDB sind die Indizes die auch auf tief liegende Felder (z.B. comments.date) gelegt werden können.
Ebenfalls hervorzuheben ist das auch große Binärdateien mit GridFS gleich mitverwaltet werden können.
Auch die Dokumentation (PHP) ist für ein jüngeres Projekt sehr gut!

MongoDB hat im Vergleich zu anderen NoSQL-Datenbanken noch eine recht hohe Ähnlichkeit zu SQL-Datenbanken. Das macht den Übergang einfacher.

Alternative: CouchDB

Allgemein ist das NoSQL-Biotop noch sehr unübersichtlich. Es gibt viele verschieden Ansätze (Dokument-, Zeilen- oder Key-Value-orientiert) mit jeweils vielen verschiedenen Produkten.
Ein ähnliches Produkt unter den bekannteren Namen ist CouchDB. Im direktem Vergleich MongoDB vs. CouchDB hat MongoDB Vorteile durch eine bessere echte PHP-API, In-Place-Updates und dem leichteren Umstieg. CouchDB punktet vor allem mit größerer Datensicherheit und unabhängigerer Entwicklercommunity.

Wann lohnt sich NoSQL?

Dokumentenorientierte Datenbank wie MongoDB und CouchDB haben Vorteile wenn viele verschiedene Datenfelder am Ende ein Dokument (z.B. Blog-Eintrag oder CMS-Seite) darstellen und man sich viel Flexibilität in der Entwicklung wünscht.
Weniger geeignet scheinen NoSQL-Systeme für Aufgaben aus dem Rechnungswesen die viele variierende Aggregationen aus Zahlenwerten benötigen.

Fazit

NoSQL ist natürlich auch ein Buzzword und SQL-Datenbanken werden selbstverständlich auch weiterhin gebraucht. Trotz alle dem bringt die NoSQL-Welle viele interessante neue Ansätze die sicherlich in einigen Bereichen in Zukunft zum Standard gehören werden.

Written by Florian Heinze

Dezember 14th, 2010 at 10:42 am

Posted in PHP

Tagged with , ,

8 Responses to 'NoSQL: Ein Einstieg mit MongoDB'

Subscribe to comments with RSS or TrackBack to 'NoSQL: Ein Einstieg mit MongoDB'.

  1. War es bei MongoDB nicht so, dass man mind. eine Hand voll Server braucht um die Daten konsistent zu bekommen, weil die Daten nicht direkt auf die Platte geschrieben werden? Wobei ich glaube, dass das bei kleinen Anwendungen erstmal nicht auffällt.

    Arvid Bergelmir

    14 Dez 10 at 13:57

  2. Eine hübsche für MongoDB gibt es auf von Doctrine. Das ganze ist ziehmlich schlicht gehalten und ermöglicht einen schnellen Einstieg in MongoDB auf PHP Basis.

    Das hübsche dabei: man hat alle Daten als Obejekte vorliegen und muss sich nicht mit umständlichen Abfragen plagen!

    Wer einen Blick darauf werfen möchte: Doctrine MongoDB Object Document Mapper => http://www.doctrine-project.org/projects/mongodb_odm

    Alexander Koß

    14 Dez 10 at 14:21

  3. @Arvid:
    Das Problem besteht nicht (mehr). Inzwischen haben sie eine sehr flexible Lösung mit der man sich für jeden Insert einzelnd entscheiden kann ob Performance oder Datensicherheit wichtiger ist (“safe”- und “fsync”-Optionen, http://de.php.net/manual/en/mongocollection.insert.php). Finde ich eine gute Lösung.
    Das Top-Produkt für Datensicherheit ist und will MongoDB aber wohl auch nicht sein.

    @Alexander:
    Leider hab ich es noch nicht ausprobieren können. Sieht aber interessant aus. Mit Doctrine 1.X mit einer MySQL war ich sehr zufrieden.

    Florian Heinze

    14 Dez 10 at 19:20

  4. […] NoSQL: Einstieg mit MongoDB. […]

  5. X mit einer MySQL war ich sehr zufrieden.

    Jacke Moncler

    10 Jan 11 at 04:45

  6. Wie würde man in diesem Beispiel dann alle posts mit einem bestimmten tag abfragen?

    mindyk

    24 Sep 12 at 15:08

  7. Die Antwort auf die Frage von @mindyk würde mich auch interessieren.

    Juri

    18 Okt 12 at 09:58

  8. @Juri dein glück das ich seit dem 24 Sep fleißig war (- :
    der query ist relativ einfach “{tags : “footag”}” oder in php find(array(‘tags’ => ‘footag’)); wenn du nach mehr als einen tag suchen möchtest {$and : [{tags : ‘footag’}, {tags: ‘foobar’}]} ähnlich für OR. Zu empfehlen wäre ein index auf tags (- :

    mindyk

    18 Okt 12 at 14:56

Leave a Reply

You can add images to your comment by clicking here.