de.comp.lang.php.* FAQ

16.5. Wie kann ich meine Datenbankperformance steigern?

Antwort von Kristian Köhntopp

Bei jeder Art von Performancetuning ist das Wichtigste zunächst einmal eine Messung. Es kommt ganz entscheidend darauf an, als erstes festzustellen, was denn genau langsam ist, bevor man sich daran macht, die Dinge zu verändern. Wenn ein Script mit Datenbankzugriff zu langsam ist, dann kann dies mehrere Ursachen haben:

Die Datenbank steht offsite oder ist nur langsam erreichbar.

Wenn die Datenbank nicht auf derselben Maschine läuft wie der Webserver, dann findet die Kommunikation zwischen Datenbank-Client und Server nicht mehr über schnelle Kommunikationsmethoden wie shared memory oder UNIX Domain Sockets statt, sondern über eine TCP/IP-Verbindung, die eine wesentlich geringere Kapazität und wesentlich höhere Latenzzeiten hat. Dies hat besonders fatale Auswirkungen, wenn die Datenbank und der Webserver durch ein langsames Netzwerk getrennt sind (Umlaufzeiten für Pakete von 10ms und mehr) oder wenn die Netzwerkbandbreite eingeschränkt ist (8 KB/sec und weniger).

Hier kommt es ganz entscheidend darauf an, die Anzahl der Anfragen pro Seitenaufbau zu vermindern und die Menge der übertragenen Daten zu verringern. Die Anzahl der Abfragen lässt sich dadurch vermindern, dass man SQL JOIN-Operationen statt vieler Abfragen verwendet. Ein typisches, falsches Konstrukt ist

// Liste der Treffer bestimmen
$result=do_database_query("select id from tabelle where $bedingung");

// Treffer anzeigen
foreach ($result as $k => $v) {
  $detail = do_detail_query("select * from tabelle2 where id =$v");
  show_detail($detail);
}

Dieser Code generiert eine Masse von Queries nacheinander. Für jede einzelne Query wird ein Umlauf zur Datenbank und zurück notwendig und so summieren sich diese Umlaufzeiten zu gigiantischen Wartezeiten beim Seitenaufbau. Viel geschickter ist stattdessen

// Treffer bestimmen
$detail = do_database_query("select * from tabelle, tabelle2
 where ( $bedingung ) and tabelle.id = tabelle2.id");
foreach ($detail as $k => $v) {
  show_detail($v);
}

Dies liefert die gewünschten Daten mit einer einzigen Query.

Die Datenbank hat hohe Verbindungsaufbaukosten und es wird CGI PHP verwendet.

Einigen Datenbanken, wie z. B. MySQL, macht es nichts aus, Datenbanklinks zu öffnen und wieder zu schließen. Andere Datenbanken, wie z. B. Oracle, starten bei jedem Connect einen eigenen Clientprozess. Dies ist ein sehr aufwendiger Vorgang. Wenn CGI PHP verwendet wird, dann endet der CGI Interpreter am Ende jeder Seite und mit dem Interpreter werden auch alle geöffneten Dateihandles und damit auch alle Datenbankverbindungen geschlossen - der Clientprozess der Datenbank endet und muss für eine neue Seite neu geladen und gestartet werden.

In solchen Fällen ist die Verwendung eines PHP-Interpreters als Modul vorzuziehen, weil in dieser Konfiguration die mit pconnect() geöffneten Links über die Lebensdauer einer PHP-Seite hinaus gehalten und auf neuen Seiten wiederverwendet werden können.

Die Queries in der Datenbank sind nicht effizient.

Alle Datenbanken haben Werkzeuge zur Analyse von Anfragen. In MySQL ist dies das EXPLAIN Kommando, in Oracle ist es EXPLAIN PLAN. Die Ausgabe dieser Kommandos sollte man in jedem Fall verstehen lernen und zu Rate ziehen. Nur so kann man erkennen, ob Indizes zur Beschleunigung der Query verwendet werden, ob die Typen von Key und Foreign Key zueinander kompatibel sind und ob die Datenbank die richtige Tabelle als treibende Tabelle in einem JOIN verwendet.

Valid HTML 4.01! Valid CSS!

16.5. Wie kann ich meine Datenbankperformance steigern?
http://www.php-faq.de/q/q-db-performance.html
de.comp.lang.php.* FAQ | (c) Copyright 2000-2007 Das dclp-FAQ-Team