Zend_Db_Profiler puede habilitarse para permitir el perfilado de
consultas. Los perfiles incluyen las consultas procesadas por el adaptador, así
como el tiempo transcurrido para ejecutar las consultas, permitiendo inspeccionar las
consultas que se han realizado sin necesidad de añadir código de
depuración adicional a las clases. El uso avanzado también permite al
desarrollador filtrar qué consultas se perfilan.
Habilite el perfilador pasando una directiva al constructor del adaptador, o pidiendo al adaptador que lo habilite más tarde.
$params = array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test'
'profiler' => true // turn on profiler
// set to false to disable (disabled by default)
);
$db = Zend_Db::factory('PDO_MYSQL', $params);
// turn off profiler:
$db->getProfiler()->setEnabled(false);
// turn on profiler:
$db->getProfiler()->setEnabled(true);
El valor de la opción 'profiler' es flexible. Se interpreta de manera diferente según su tipo. La mayoría de las veces, debe usar un valor booleano simple, pero otros tipos le permiten personalizar el comportamiento del perfilador.
Un argumento booleano establece el perfilador como habilitado si es un valor
TRUE, o deshabilitado si es FALSE. La clase del
perfilador es la clase de perfilador predeterminada del adaptador,
Zend_Db_Profiler.
$params['profiler'] = true;
$db = Zend_Db::factory('PDO_MYSQL', $params);
Una instancia de un objeto perfilador hace que el adaptador use ese objeto. El tipo del objeto
debe ser Zend_Db_Profiler o una subclase del mismo. Habilitar el
perfilador se hace por separado.
$profiler = MyProject_Db_Profiler();
$profiler->setEnabled(true);
$params['profiler'] = $profiler;
$db = Zend_Db::factory('PDO_MYSQL', $params);
El argumento puede ser un array asociativo que contenga cualquiera o todas las claves
'enabled', 'instance', y
'class'. Las claves 'enabled' y
'instance' corresponden a los tipos booleano e instancia
documentados anteriormente. La clave 'class' se usa para nombrar una clase a
usar para un perfilador personalizado. La clase debe ser Zend_Db_Profiler o
una subclase. La clase se instancia sin argumentos de constructor. La
opción 'class' se ignora cuando se proporciona la opción
'instance'.
$params['profiler'] = array(
'enabled' => true,
'class' => 'MyProject_Db_Profiler'
);
$db = Zend_Db::factory('PDO_MYSQL', $params);
Finalmente, el argumento puede ser un objeto de tipo Zend_Config
que contenga propiedades, que se tratan como las claves de array descritas anteriormente. Por ejemplo,
un archivo "config.ini" podría contener los siguientes datos:
[main] db.profiler.class = "MyProject_Db_Profiler" db.profiler.enabled = true
Esta configuración se puede aplicar mediante el siguiente código PHP:
$config = new Zend_Config_Ini('config.ini', 'main');
$params['profiler'] = $config->db->profiler;
$db = Zend_Db::factory('PDO_MYSQL', $params);
La propiedad 'instance' se puede usar como en el siguiente ejemplo:
$profiler = new MyProject_Db_Profiler();
$profiler->setEnabled(true);
$configData = array(
'instance' => $profiler
);
$config = new Zend_Config($configData);
$params['profiler'] = $config;
$db = Zend_Db::factory('PDO_MYSQL', $params);
En cualquier momento, obtenga el perfilador usando el método
getProfiler() del adaptador:
$profiler = $db->getProfiler();
Esto devuelve una instancia de objeto Zend_Db_Profiler. Con
esa instancia, el desarrollador puede examinar sus consultas usando una
variedad de métodos:
getTotalNumQueries()devuelve el número total de consultas que se han perfilado.getTotalElapsedSecs()devuelve el número total de segundos transcurridos para todas las consultas perfiladas.getQueryProfiles()devuelve un array con todos los perfiles de consulta.getLastQueryProfile()devuelve el último (más reciente) perfil de consulta, sin importar si la consulta ha finalizado o no (si no lo ha hecho, la hora de finalización seráNULL)clear()elimina cualquier perfil de consulta pasado de la pila.
El valor de retorno de getLastQueryProfile() y los
elementos individuales de getQueryProfiles() son
objetos Zend_Db_Profiler_Query, que proporcionan la
capacidad de inspeccionar las consultas individuales en sí mismas:
getQuery()devuelve el texto SQL de la consulta. El texto SQL de una sentencia preparada con parámetros es el texto en el momento en que la consulta se preparó, por lo que contiene marcadores de posición de parámetros, no los valores usados cuando la sentencia se ejecuta.getQueryParams()devuelve un array de valores de parámetros usados al ejecutar una consulta preparada. Esto incluye tanto los parámetros enlazados como los argumentos al métodoexecute()de la sentencia. Las claves de el array son los índices de parámetros posicionales (basados en 1) o nombrados (cadena).getElapsedSecs()devuelve el número de segundos que la consulta tardó en ejecutarse.
La información que proporciona Zend_Db_Profiler es útil para
perfilar cuellos de botella en aplicaciones, y para depurar consultas
que se han ejecutado. Por ejemplo, para ver la consulta exacta que se
ejecutó por última vez:
$query = $profiler->getLastQueryProfile(); echo $query->getQuery();
Quizás una página se está generando lentamente; use el perfilador para determinar primero el número total de segundos de todas las consultas, y luego recorrer las consultas para encontrar la que se ejecutó más tiempo:
$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";
Además de la inspección de consultas, el perfilador también permite al
desarrollador filtrar qué consultas se perfilan. Los siguientes
métodos operan sobre una instancia de Zend_Db_Profiler:
setFilterElapsedSecs() permite al desarrollador establecer
un tiempo mínimo de consulta antes de que una consulta se perfile. Para eliminar el
filtro, pase al método un valor NULL.
// Only profile queries that take at least 5 seconds: $profiler->setFilterElapsedSecs(5); // Profile all queries regardless of length: $profiler->setFilterElapsedSecs(null);
setFilterQueryType() permite al desarrollador establecer
qué tipos de consultas deben perfilarse; para perfilar múltiples
tipos, combínelos con un OR lógico. Los tipos de consulta se definen como las siguientes
constantes de Zend_Db_Profiler:
Zend_Db_Profiler::CONNECT: operaciones de conexión, o selección de una base de datos.Zend_Db_Profiler::QUERY: consultas generales de base de datos que no coinciden con otros tipos.Zend_Db_Profiler::INSERT: cualquier consulta que añade nuevos datos a la base de datos, generalmente SQL INSERT.Zend_Db_Profiler::UPDATE: cualquier consulta que actualiza datos existentes, usualmente SQL UPDATE.Zend_Db_Profiler::DELETE: cualquier consulta que elimina datos existentes, usualmente SQLDELETE.Zend_Db_Profiler::SELECT: cualquier consulta que recupera datos existentes, usualmente SQL SELECT.Zend_Db_Profiler::TRANSACTION: cualquier operación transaccional, como iniciar transacción, confirmar (commit), o revertir (rollback).
Al igual que con setFilterElapsedSecs(), puede eliminar cualquier
filtro existente pasando NULL como único
argumento.
// profile only SELECT queries
$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT);
// profile SELECT, INSERT, and UPDATE queries
$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT |
Zend_Db_Profiler::INSERT |
Zend_Db_Profiler::UPDATE);
// profile DELETE queries
$profiler->setFilterQueryType(Zend_Db_Profiler::DELETE);
// Remove all filters
$profiler->setFilterQueryType(null);
Usar setFilterQueryType() puede reducir la cantidad de
perfiles generados. Sin embargo, a veces puede ser más útil
mantener todos los perfiles, pero ver solo los que necesita en un momento
dado. Otra característica de getQueryProfiles() es
que puede realizar este filtrado sobre la marcha, pasando un tipo de
consulta (o combinación lógica de tipos de consulta) como su primer
argumento; consulte esta
sección para obtener una lista de las constantes de tipo de consulta.
// Retrieve only SELECT query profiles
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT);
// Retrieve only SELECT, INSERT, and UPDATE query profiles
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT |
Zend_Db_Profiler::INSERT |
Zend_Db_Profiler::UPDATE);
// Retrieve DELETE query profiles
$profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::DELETE);
Un Perfilador Especializado es un objeto que hereda de
Zend_Db_Profiler. Los Perfiladores Especializados tratan
la información de perfilado de maneras específicas.
Zend_Db_Profiler_Firebug envía información de perfilado a la
Firebug Console.
Todos los datos se envían a través del componente Zend_Wildfire_Channel_HttpHeaders
que usa cabeceras HTTP para asegurar que el contenido de la página no se
vea alterado. Depurar solicitudes AJAX que requieren respuestas limpias de
JSON y XML es posible con este enfoque.
Requisitos:
Navegador Firefox, idealmente versión 3, aunque la versión 2 también es compatible.
Extensión de Firefox Firebug, que puede descargar en https://addons.mozilla.org/en-US/firefox/addon/1843.
Extensión de Firefox FirePHP, que puede descargar en https://addons.mozilla.org/en-US/firefox/addon/6149.
Ejemplo 27.45. Perfilado de BD con Zend_Controller_Front
// In your bootstrap file
$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);
// Attach the profiler to your db adapter
$db->setProfiler($profiler);
// Dispatch your front controller
// All DB queries in your model, view and controller
// files will now be profiled and sent to Firebug
Ejemplo 27.46. Perfilado de BD sin Zend_Controller_Front
$profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);
// Attach the profiler to your db adapter
$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);
// Start output buffering
ob_start();
// Now you can run your DB queries to be profiled
// Flush profiling data to browser
$channel->flush();
$response->sendHeaders();