Get Adobe Flash player

SQL

Performancegewinn durch Rechenarbeit auf der
Datenbank

PHP ist ja bekannt dafür, gerne und gut mit der OS-Datenbank MySQL zusammenzuarbeiten. Kein Wunder also, dass diese die mit Abstand am meisten genutzte Datenbank für dynamische PHP-Webanwendungen weltweit ist.

Aufs einfachste reduziert gibt es immer zwei grundlegende Tätigkeiten: man holt sich Daten aus der Datenbank, oder man füttert sie mit solchen. Besonders bei der erstgenannten Variante, dem Lesen aus der Datenbank, wird vor dem abschließenden Schritt (etwa eine Ausgabe im Browser oder in einer Datei) häufig noch Arbeit in die Manipulation der Daten auf PHP-Seite gesteckt. Bei großen Datenmengen führt dies häufig zu starken Performance-Belastungen. Leider sieht man in solchem Code allzu häufig Dinge, die viel einfacher bereits beim SELECT auf Datenbankebene hätten gelöst werden können.

Es gilt die Grundregel, nur die Daten aus der Datenbank zu holen, die auch benötigt werden und nicht skriptseitig das unnötige Material auszufiltern.

Gleiches gilt für Formatierungen. Auch hier bietet SQL viele Werkzeuge, die verwendet werden können und das sollte man auch tun. Typische Anwendungen sind also:

  1. Umformatierungen (etwa bei Datumfeldern)
  2. Teile von Strings ermitteln und gruppieren (etwa die Domain bei E-Mail-Adressen)
  3. Einfaches Zählen von Datengruppen
  4. u.v.m.

Sehen wir uns an einem typischen Beispiel das Gruppieren von Datumsfeldern an: Wir haben eine Kundendatenbank und sollen die Altersstruktur ermitteln. Wichtig dabei ist zu wissen, wie viele Kunden es für jede der folgenden Altersgruppe gibt:

  • unter 18 Jahre
  • 18 – 30 Jahre
  • 30 – 55 Jahre
  • über 55 Jahre

Ein typischer ‚php‘-Weg wäre, das Geburtsdatum eines jeden Datensatzes zu ermitteln und beim Durchlaufen der Ergebnissmenge das aktuelle Alter zu errechnen und je nach dem, in welchem Altersbereich sich das Ergebnis befindet, eine der vier angelegten Variablen (für jede interessante Altersgruppe eine) um einen Wert hoch zuählen. Das ist natürlich umständlich und besonders bei großen Tabellen mit beispielsweise 500.000 oder mehr Datensätzen sollte hier auch die Performance unbedingt berücksichtigt werden. Eine PDO-Variante sähe beispielsweise so aus (Fehlerbehandlung geht besser, ich weiß):

// Daten aus Datenbank ermitteln
try
{
    $sql = 'SELECT
                   DATE_ADD(geburtsdatum, INTERVAL 18 YEAR) > now() AS under18,
                   (DATE_ADD(geburtsdatum, INTERVAL 18 YEAR) < now() AND DATE_ADD(geburtsdatum, INTERVAL 30 YEAR) > now()) AS 18to30,
                   (DATE_ADD(geburtsdatum, INTERVAL 30 YEAR) < now() AND DATE_ADD(geburtsdatum, INTERVAL 55 YEAR) > now()) AS 30to55,
                   DATE_ADD(geburtsdatum, INTERVAL 55 YEAR) < now() AS over55,
                   COUNT(*) AS number
               FROM
                   kunden
               GROUP BY
                   under18,18to30,30to55,over55';
 
    $stmt = $dbh->prepare($sql);
    $stmt->execute();
 
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
    {
		if ($row['under18'] == 1)
		{
			$under18 = $row['number'];
		}
 
		if ($row['18to30'] == 1)
		{
			$_18to30 = $row['number'];
		}
 
		if ($row['30to55'] == 1)
		{
			$_30to55 = $row['number'];
		}
 
		if ($row['over55'] == 1)
		{
			$over55 = $row['number'];
		}
    }
}
catch(PDOException $e)
{
	echo 'Fehler bei der Ermittlung der Daten:<br /><br />' . $e->getMessage();
}

Hier werden bei dem Query bereits genau die vier Zahlen ermittelt, die von Bedeutung sind. Verwendet wird dabei die DATE_ADD-Funktion.

Weiterführende Informationen zu den umfangreichen Funktionen, die MySQL bietet:

Man beachte dort auch die ‚Section Navigation‘ auf der rechten Seite, die zu weiteren Funktionsbereichen von MySQL führt.