9.2. Zend_Db_Profiler

9.2.1. Introduction

Zend_Db_Profiler peut être activé pour permettre le profilage de requêtes. Les profils incluent les requête exécutées par l'adaptateur, ainsi que leur temps d'exécution, permettant l'inspection des requêtes qui ont été exécutées sans avoir besoin de rajouter du code spécifique de débogage aux classes. L'utilisation avancée permet aussi au développeur de filtrer quelles requêtes il souhaite profiler.

Le profileur s'active soit en passant une directive au constructeur de l'adaptateur, soit en spécifiant à l'adaptateur de l'activer plus tard.

<?php
require_once 'Zend/Db.php';

$params = array (
    'host'     => '127.0.0.1',
    'username' => 'malory',
    'password' => '******',
    'dbname'   => 'camelot',
    'profiler' => true  // active le profiler; mettre à false pour désactiver (valeur par défaut)
);

$db = Zend_Db::factory('PDO_MYSQL', $params);

// coupe le profileur :
$db->getProfiler()->setEnabled(false);

// active le profileur :
$db->getProfiler()->setEnabled(true);
?>

9.2.2. Utiliser le profileur

A n'importe quel moment, vous pouvez récupérer le profileur en utilisant la méthode getProfiler() de l'adaptateur :

<?php
$profileur = $db->getProfiler();
?>

Ceci retourne une instance de Zend_Db_Profiler. Avec cette instance, le développeur peut examiner les requêtes en utilisant un éventail de méthodes :

  • getTotalNumQueries() retourne le nombre total de requêtes profilées.

  • getTotalElapsedSecs() retourne le nombre total de secondes écoulées pour chaque requête profilée.

  • getQueryProfiles() retourne un tableau de tous les profils de requêtes.

  • getLastQueryProfile() retourne le profil de requête le plus récent, peut importe si la requête à fini de s'exécuter ou pas (si l'exécution n'est pas finie, le temps de fin sera null).

  • clear() nettoie tous les anciens profils de la pile.

La valeur de retour de getLastQueryProfile() et les élements individuels de getQueryProfiles() sont des objets de type Zend_Db_Profiler_Query qui permettent d'inspecter les requêtes :

  • getQuery() retourne le SQL de la requête sous forme de texte.

  • getElapsedSecs() retourne le nombre de secondes d'exécution de la requête.

L'information que Zend_Db_Profiler founi est utile pour profiler des goulets d'étranglement dans les applications, ainsi que pour déboguer les requêtes qui viennent d'être exécutées. Par exemple, pour voir la dernière requête qui vient de s'exécuter :

<?php
$query = $profileur->getLastQueryProfile();

echo $query->getQuery();
?>

Si une page se génère lentement, utilisez le profileur pour déterminer le nombre total de requêtes, et ensuite passer d'une requête à l'autre pour voir laquelle a été la plus longue:

<?php
$tempsTotal       = $profileur->getTotalElapsedSecs();
$nombreRequetes   = $profileur->getTotalNumQueries();
$tempsLePlusLong  = 0;
$requeteLaPlusLongue = null;

foreach ($profileur->getQueryProfiles() as $query) {
    if ($query->getElapsedSecs() > $tempsLePlusLong) {
        $tempsLePlusLong  = $query->getElapsedSecs();
        $requeteLaPlusLongue = $query->getQuery();
    }
}

echo 'Exécution de ' . $nombreRequetes . ' requêtes en ' . $tempsTotal . ' secondes' . "\n";
echo 'Temps moyen : ' . $tempsTotal / $nombreRequetes . ' secondes' . "\n";
echo 'Requêtes par seconde: ' . $nombreRequetes / $tempsTotal . ' seconds' . "\n";
echo 'Requête la plus lente (secondes) : ' . $tempsLePlusLong . "\n";
echo "Requête la plus lente (SQL) : \n" . $requeteLaPlusLongue . "\n";
?>

9.2.3. Utilisation avancée du profileur

En plus de l'inspection de requête, le profileur permet aussi au développeur de filtrer quelles requêtes il veut profiler. Les méthodes suivantes fonctionnent avec une instance de Zend_Db_Profiler :

9.2.3.1. Filtrer par temps d'exécution

setFilterElapsedSecs() permet au développeur de définir un temps minimum d'exécution de la requête avant que celle-ci soit profilée. Pour retirer le filtre, passez une valeur null à la méthode.

<?php
// Seules les requêtes qui durent au moins 5 secondes sont profilées:
$profileur->setFilterElapsedSecs(5);

// Profil de toutes les requête, peu importe leur longueur:
$profileur->setFilterElapsedSecs(null);
?>

9.2.3.2. Filtrer par type de requête

setFilterQueryType() permet au développeur de définir quels types de requêtes doivent être profilés ; pour profiler des types multiples vous pouvez utiliser le OU logique. Les types de requêtes sont définis sous forme de constantes de Zend_Db_Profiler :

  • Zend_Db_Profiler::CONNECT : opérations de connexion ou de sélection de base de données.

  • Zend_Db_Profiler::QUERY : requête générale qui ne correspond pas aux autres types.

  • Zend_Db_Profiler::INSERT : toute requête qui ajoute des données dans la base de données, généralement INSERT.

  • Zend_Db_Profiler::UPDATE : toute requête qui met à jour des données, généralement UPDATE.

  • Zend_Db_Profiler::DELETE : toute requête qui efface des données, généralement DELETE.

  • Zend_Db_Profiler::SELECT : toute requête qui récupère des données, généralement SELECT.

  • Zend_Db_Profiler::TRANSACTION : toute requête qui concerne des opérations de transaction, comme start transaction, commit, ou rollback.

Comme avec setFilterElapsedSecs(), vous pouvez retirer tous les filtres en passant null comme unique argument.

<?php
// profile uniquement les requêtes SELECT
$profileur->setFilterQueryType(Zend_Db_Profiler::SELECT);

// profile les requêtes SELECT, INSERT, et UPDATE
$profileur->setFilterQueryType(Zend_Db_Profiler::SELECT | Zend_Db_Profiler::INSERT | Zend_Db_Profiler::UPDATE);

// profile les requêtes DELETE
$profileur->setFilterQueryType(Zend_Db_Profiler::DELETE);

// Efface tous les filtres
$profileur->setFilterQueryType(null);
?>

9.2.3.3. Récupérer les profils par type de requête

Utiliser setFilterQueryType() peut réduire les profils générés. Cependant il est parfois utile de garder tous les profils et voir uniquement ceux dont on a besoin, à un moment donné. Une autre possibilité de getQueryProfiles() est qu'il est possible de filtrer à la volée, en passant un type de requête (ou une combinaison logique de types de requête) comme premier argument ; voir Section 9.2.3.2, « Filtrer par type de requête » pour une liste des constantes de types de requête.

            <?php
// Récupère uniquement les profils des requêtes SELECT
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT);

// Récupère uniquement les profils des requêtes SELECT, INSERT, et UPDATE
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT | Zend_Db_Profiler::INSERT | Zend_Db_Profiler::UPDATE);

// Récupère uniquement les profils des requêtes DELETE (on peut donc comprendre pourquoi les données
// disparaissent)
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::DELETE);
?>