Home

Projekte

Notizen

Bücherregal

Mitwirkende

Notizen /

Dateien Vs. Datenbank

Ein kleiner Benchmark, der den lesenden Zugriff auf Dateien unter PHP mit dem lesenden Zugriff auf eine Datenbank vergleicht. Achtung: Die Tests sind lediglich runtergehackt. Die Aussagekraft der Ergebnisse ist durchaus fragwürdig.

Motivation

Diese Seite basiert auf einem Wiki. Als ich mich nach geeigneten Wiki-Implementierungen für mein Notizbuch umsah, stellte ich fest, dass eine ganze Menge Wikis auf Dateien statt auf eine Datenbank als Backend aufsetzen. Manche behaupten sogar ein dateibasiertes Backend sei für im Falle von Wikis schneller als ein Datenbankbankend. Werfen wir einen Blick auf die (etwas vereinfachten) Anforderungen an ein Wikibackend.

  • Lesezugriffe: Es gibt mindestens einen Lesezugriff bei jedem Klick auf der Seite. Dabei wird meist ein ein einzelner Datensatz gelesen. Dieser Datensatz wird meist über einen Namen identifiziert.
  • Schreibzugriffe: Im Verhältnis zu Lesezugriffen sind Schreibzugriffe vergleichsweise selten. Fallen also mit Blick auf die Performance kaum ins Gewicht.
  • Besondere Zugriffe: Die meisten Wikis (so auch dieses) haben Suchfunktionen. Es kann nach einfachen Worten im Text gesucht werden oder z.B. auch nach Backlinks. Da hier verstärkt Indextechniken und Caching zu Einsatz kommen ist ein vereinfachter Datei-Lese-Benchmark wohl wenig sinnvoll um derartige Zugriffe zu evaluieren.

Konzentrieren wir uns mal auf die Lesezugriffe.

Testsetup

Zum Testen dienen die ersten 4kb des "infamous" Lorem Ipsum. Dieser wird 2000 mal in eine Datenbanktabelle und 2000 mal in verschiedene Dateien eingefügt. Die Testtabelle hat also 2000 Datensätze, der Testordner enthält 2000 Dateien. Die Datensätze und die Dateien sollen über Ihren Namen identifiziert werden. Die Namen der Dateien und der Testdatensätze sind

lorem.ipsum.[0-1999]

Der Lorem Ipsum Text soll im nächsten Schritt 2000 mal aus der Datenbank bzw. aus den einzelnen Dateien gelesen werden, und in einer Variablen gespeichert werden.

Datenbank

Es wurde hier keine Datenbankabstratktion verwendet um keinen unnötigen Overhead hinzuzufügen. Die einfachen MySQL-Funktionen müssen reichen. Der Code sieht folgendermaßen aus:

<?php
/** PEAR-Timer starten */
require_once 'Benchmark/Timer.php';
$timer = new Benchmark_Timer();
$timer->setMarker('Start');

/** Verbinden */
$link = mysql_connect('localhost', 'root', '');
mysql_select_db('benchtest');

/** 2000 Abfragen auf die Datenbank */
for ($i = 0; $i < 2000; ++$i) {
    $name = 'lorem.ipsum.'.$i;
    $query = 'SELECT * FROM lorem " .
        "WHERE name = "'.$name.'"';
    $res = mysql_query($query, $link);
    $array = mysql_fetch_array($res);
    $lorem = $array[1];

    /** Test auf 'Lorem'
    if (!substr($lorem, 0, 5) == 'Lorem') {
        die ('Kein Lorem');
    }
}

/** Verbindung schliessen */
mysql_close($link);

/** Timer stopen */
$timer->setMarker('Stop');
echo $timer->timeElapsed('Start', 'Stop') ."\n";
?>

Dieses Skript kam beim ersten Lauf die sagenhafte Zeit von 114.69 Sekunden!! Wow, was war falsch gelaufen? Klar, Index über der "name"-Spalte vergessen. Nachgeholt. Entgültig im Mittel gemessene Zeit:

1.487 Sek

Anmerkung: Dieser Test zeigt noch einmal wie unglaublich wichtig Indizes im Datenbankdesign sind!

Die Datei-Version

Die Dateiversion tut genau das gleiche: 2000 mal Lorem Ipsum aus 2000 verschiedenen Dateien lesen:

<?php
/** Timer starten **/
require_once 'Benchmark/Timer.php';
$timer = new Benchmark_Timer();
$timer->setMarker('Start');

/** Dateien lesen */
for ($i = 0; $i < 2000; ++$i) {
    $name = 'files/lorem.ipsum.'.$i;
    $lorem = file_get_contents($name);

    /** Auf Lorem testen */
    if (!substr($lorem, 0, 5) == 'Lorem') {
        die ('Kein Lorem');
    }
}

// Timer stopen
$timer->setMarker('Stop');
echo $timer->timeElapsed('Start', 'Stop') ."\n";
?>

Abgesehen davon, dass dieser Code um einiges kürzer ist, ist er im Mittel auch deutlich schneller. Entgültig gemessene Zeit:

0.483 Sek

Das ist im Schnitt 3-mal so schnell wie die Datenbank und das bei wesentlich einfacherem Code. Und mit dem Dateisystem und dem Festplattencache ist der Index quasi schon mit eingebaut.

Fazit

1.487 Sek zu 0.483 Sek für die Dateien. Wer einfache Datenmodelle hat, und Wikis haben recht einfache Datenmodelle, sollte sich durchaus überlegen, ob es nicht sinnvoller ist Daten in Dateien zu schreiben als für jede noch so kleine Aufgabe eine Datenbank zu verwenden. Möglicherweise produziert die Datenbank nämlich einen größeren Overhead als ein einfacher Dateizugriff. Das gilt übrigens auch für den Code. Datenbankzugriffe sind für gewöhnlich um einiges wortreicher als Dateizugriffe.

Tags: PHP ,Benchmark

Letzte Änderung am 05.07.2006 01:44 Uhr