Zend_Db_Profiler
Einführung
Zend_Db_Profiler kann aktiviert werden, um das Erstellen von
Profilen für Abfragen zu erlauben. Die Profile enthalten die Abfragen, die durch den
Adapter verarbeitet worden sind, sowie die Laufzeit der Abfragen, um die Kontrolle der
verarbeiteten Abfragen zu ermöglichen, ohne das extra Code für das Debugging zu den
Klassen hinzugefügt werden muß. Die erweiterte Verwendung ermöglicht den Entwickler
sogar zu filtern, welche Abfragen aufgezeichnet werden sollen.
Der Profiler wird entweder durch die Übergabe eines Parameters an den Konstruktor des
Adapters oder zu einem späteren Zeitpunkt direkt an den Adapter aktiviert.
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test',
'profiler' => true // aktiviere den Profiler; false, um ihn zu
// deaktivieren (standardmäßig deaktiviert)
);
$db = Zend_Db::factory('PDO_MYSQL', $params);
// deaktiviere Profiler
$db->getProfiler()->setEnabled(false);
// aktiviere Profiler
$db->getProfiler()->setEnabled(true);
Der Wert der profiler Option ist flexibel. Er wird unterschiedlich
interpretiert, abhängig von seinem Typ. Meistens sollte ein einfacher Boolscher Wert
verwendet werden, aber andere Typen ermöglichen es das Verhalten des Profilers
anzupassen.
Ein boolsches Argument aktiviert den Profiler wenn es der Wert TRUE
ist, oder schaltet ihn mit FALSE aus. Die Profiler Klasse ist die
Standard Profiler Klasse des Adapters Zend_Db_Profiler.
$params['profiler'] = true;
$db = Zend_Db::factory('PDO_MYSQL', $params);
Eine Instanz eines Profiler Objektes führt dazu das der Adapter dieses Objekt verwendet.
Der Typ des Objektes muß hierfür Zend_Db_Profiler oder eine
Subklasse sein. Der Profiler muß separat eingeschaltet werden.
$profiler = MyProject_Db_Profiler();
$profiler->setEnabled(true);
$params['profiler'] = $profiler;
$db = Zend_Db::factory('PDO_MYSQL', $params);
Ein Argument kann ein assoziatives Array sein das eines oder alle der folgenden
Schlüssel enthält: 'enabled', 'instance', oder
'class'. Die Schlüssel 'enabled' und
'instance' korrespondieren zu den zuvor dokumentierten boolschen
und Instanz Typen. Der 'class' Schlüssel wird verwendet um die
Klasse die für einen eigenen Profiler verwendet werden soll, zu benennen. Die Klasse muß
Zend_Db_Profiler oder eine Subklasse sein. Die Klasse wird ohne
Konstruktor Argumente instanziert. Die 'class' Option wird
ignoriert wenn die 'instance' Option angegeben wurde.
$params['profiler'] = array(
'enabled' => true,
'class' => 'MyProject_Db_Profiler'
);
$db = Zend_Db::factory('PDO_MYSQL', $params);
Letztendlich kann das Argument ein Objekt des Typs Zend_Config
sein das Eigenschaften enthält welche als Array Schlüssel verwendet werden wie anbei
beschrieben. Zum Beispiel könnte die Datei "config.ini" die
folgenden Daten enthalten:
[main]
db.profiler.class = "MyProject_Db_Profiler"
db.profiler.enabled = true
Diese Konfiguration kann durch den folgenden PHP Code angesprochen
werden:
$config = new Zend_Config_Ini('config.ini', 'main');
$params['profiler'] = $config->db->profiler;
$db = Zend_Db::factory('PDO_MYSQL', $params);
Die Eigenschaft 'instance' kann wie folgt verwendet werden:
$profiler = new MyProject_Db_Profiler();
$profiler->setEnabled(true);
'instance' => $profiler
);
$config = new Zend_Config($configData);
$params['profiler'] = $config;
$db = Zend_Db::factory('PDO_MYSQL', $params);
Den Profiler verwenden
Der Profiler kann jederzeit über die Adapter Methode
getProfiler() geholt werden:
$profiler = $db->getProfiler();
Dies gibt eine Zend_Db_Profiler Objektinstanz zurück. Mit dieser
Instanz kann der Entwickler seine Abfragen mit Hilfe von verschiedenen Methoden
untersuchen:
-
getTotalNumQueries() gibt die Gesamtzeit aller
aufgezeichneten Abfragen zurück.
-
getTotalElapsedSecs() gibt die gesamte Anzahl an
Sekunden für alle aufgezeichneten Abfragen zurück.
-
getQueryProfiles() gibt ein Array mit allen
aufgezeichneten Abfragen zurück.
-
getLastQueryProfile() gibt das Profil der letzten
(neuesten) Abfrage zurück, gleichgültig ob die Abfrage beendet werden konnte
oder nicht (wenn nicht, wird die Endzeit NULL sein)
-
clear() löscht jedes vorherige Abfrageprofile vom
Stapel.
Der Rückgabewert von getLastQueryProfile() und die einzelnen
Elemente von getQueryProfiles() sind
Zend_Db_Profiler_Query Objekte, welche die Möglichkeit bieten,
die individuellen Abfragen zu untersuchen:
-
getQuery() gibt den SQL Text der
Abfrage zurück. Der SQL Text des vorbereiteten Statements mit
Parametern ist der Text, zu der Zeit als die Abfrage vorbereitet wurde, er
enthält also Platzhalter für Parameter, nicht die Werte die verwendet werden
wenn das Statement ausgeführt wird.
-
getQueryParams() gibt ein Array von Parameter Werten
zurück die verwendet werden wenn eine vorbereitete Abfrage ausgeführt wird. Das
beinhaltet beide, gebundene Parameter und Argumente für die
execute() Methode des Statements. Die Schlüssel des
Arrays sind die Positionierten (1-basierend) oder benannten (Zeichenkette)
Parameter Indezes.
-
getElapsedSecs() gibt die Anzahl der Sekunden zurück,
wie lange die Abfrage gelaufen ist.
Die Informationen, die Zend_Db_Profiler bereitstellt, sind
nützlich, um Engpässe in der Anwendung zu ermitteln und um Abfragen zu überprüfen, die
durchgeführt worden sind. Um zum Beispiel die genaue Abfrage zu sehen, die zuletzt
durchgeführt worden ist:
$query = $profiler->getLastQueryProfile();
Vielleicht wird eine Seite langsam erstellt; verwende den Profiler, um zuerst die
gesamte Laufzeit aller Abfragen zu ermitteln und dann durchlaufe die Abfragen, um die
am längsten laufende zu finden:
$totalTime = $profiler->getTotalElapsedSecs();
$queryCount = $profiler->getTotalNumQueries();
$longestTime = 0;
$longestQuery = null;
foreach ($profiler->getQueryProfiles() as $query) {
if ($query->getElapsedSecs() > $longestTime) {
$longestTime = $query->getElapsedSecs();
$longestQuery = $query->getQuery();
}
}
echo 'Executed ' . $queryCount . ' queries in ' . $totalTime .
' seconds' . "\n";
echo 'Average query length: ' . $totalTime / $queryCount .
' seconds' . "\n";
echo 'Queries per second: ' . $queryCount / $totalTime . "\n";
echo 'Longest query length: ' . $longestTime . "\n";
echo "Longest query: \n" . $longestQuery . "\n";
Fortgeschrittene Profiler Verwendung
Zusätzlich zum Untersuchen von Anfragen erlaubt der Profiler dem Entwickler auch zu
filtern, welche Abfragen aufgezeichnet werden sollen. Die folgenden Methoden arbeiten
mit einer Zend_Db_Profiler Instanz:
Filtern anhand der Laufzeit der Abfragen
setFilterElapsedSecs() ermöglicht dem Entwickler, eine
minimale Laufzeit anzugeben, bevor eine Abfrage aufzeichnet werden soll. Um den
Filter zu entfernen, muss nur der Wert NULL an die Methode
übergeben werden.
// Zeichne nur Abfragen auf, die mindestens 5 Sekunden laufen:
$profiler->setFilterElapsedSecs(5);
// Zeichne alle Abfragen unabhängig von deren Laufzeit auf:
$profiler->setFilterElapsedSecs(null);
Filtern anhand des Abfragetyp
setFilterQueryType() ermöglicht dem Entwickler anzugeben,
welche Abfragetypen aufgezeichnet werden sollen; um mehrere Typen aufzuzeichnen,
verwende das logische OR. Abfragetypen sind mit den folgenden
Zend_Db_Profiler Konstanten definiert:
-
Zend_Db_Profiler::CONNECT: Verbindungsoperationen
oder Auswahl einer Datenbank .
-
Zend_Db_Profiler::QUERY: allgemeine
Datenbankabfragen, die keinem der anderen Typen entsprechen.
-
Zend_Db_Profiler::INSERT: jede Abfrage, die neue
Daten zur Datenbank hinzufügt, normalerweise ein SQL
INSERT.
-
Zend_Db_Profiler::UPDATE: jede Abfrage, die
vorhandene Daten aktualisiert, normalerweise ein SQL
UPDATE.
-
Zend_Db_Profiler::DELETE: jede Abfrage, die
vorhandene Daten löscht, normalerweise ein SQL
DELETE.
-
Zend_Db_Profiler::SELECT: jede Abfrage, die
vorhandene Daten selektiert, normalerweise ein SQL
SELECT.
-
Zend_Db_Profiler::TRANSACTION: jede
Transaktionsoperation, wie zum Beispiel START TRANSACTION, COMMIT oder
ROLLBACK.
Mit setFilterElapsedSecs() kannst du jeden vorhandenen
Filtern entfernen, indem du NULL als einziges Argument
übergibst.
// zeichne nur SELECT Abfragen auf
$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT);
// zeichne SELECT, INSERT und UPDATE Abfragen auf
$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT |
Zend_Db_Profiler::INSERT |
Zend_Db_Profiler::UPDATE);
// zeichne DELETE Abfragen auf
$profiler->setFilterQueryType(Zend_Db_Profiler::DELETE);
// Remove all filters
$profiler->setFilterQueryType(null);
Hole Profil nach Abfragetyp zurück
Die Verwendung von setFilterQueryType() kann die Anzahl
der aufgezeichneten Abfragen reduzieren. Allerdings kann es sinnvoller sein, alle
Abfragen auzuzeichnen, baer nur diese anzuschauen, die im Moment gebraucht werden.
Ein weiteres Feature von getQueryProfiles() ist das
Filtern der Abfragen "on-the-fly" durch Übergabe eines Abfragetyps (oder eine
logischen Kombination von Abfragetypen) als erstes Argument; beachte
dieses Kapitel für eine
Liste der Konstanten für Abfragetypen.
// Hole nur SELECT Abfragen zurück
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT);
// Hole nur SELECT, INSERT un UPDATE Abfragen zurück
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT |
Zend_Db_Profiler::INSERT |
Zend_Db_Profiler::UPDATE);
// Hole DELETE Abfragen zurück
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::DELETE);
Specialized Profilers
Ein spezialisierter Profiler ist ein Objekt das von
Zend_Db_Profiler abgeleitet ist. Spezialisierte Profiler
behandeln die Profilinginformationen auf speziellen Wegen.
Profilen mit Firebug
Zend_Db_Profiler_Firebug sendet Profilinginformationen an die
» Firebug
» Console.
Alle Daten werden über die Zend_Wildfire_Channel_HttpHeaders
Komponente gesendet welche HTTP Header verwendet um sicherzustellen das
der Seiteninhalt nicht gestört wird. Das Debuggen von AJAX Anfragen die
klare JSON und XML Antworten benötigen ist mit diesem
Weg möglich.
Notwendigkeiten:
Example #1 DB Profiling mit Zend_Controller_Front
// In der Bootstrap Datei
$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);
// Den Profiler an den DB Adapter anfügen
$db->setProfiler($profiler);
// Den Frontcontroller ausführen
// Alle DB Abfragen im Modell, View und Controller Dateien
// werden nun profiled und an Firebug gesendet
Example #2 DB Profiling ohne Zend_Controller_Front
$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);
// Den Profiler an den DB Adapter anfügen
$db->setProfiler($profiler);
$request = new Zend_Controller_Request_Http();
$response = new Zend_Controller_Response_Http();
$channel = Zend_Wildfire_Channel_HttpHeaders::getInstance();
$channel->setRequest($request);
$channel->setResponse($response);
// Ausgabe buffering starten
// Jetzt können DB Abfragen durchgeführt werden die auch profiled werden
// Die Profilingdaten an den Browser senden
$channel->flush();
$response->sendHeaders();
|
|