Une requête doit être considérée comme pouvant être mise en cache si elle est souvent exécutée et qu'elle a un temps d'exécution élevé. Les candidats sont trouvés en créant une liste de requêtes triées par le produit du nombre d'exécutions, multiplié par le temps d'exécution de la requête. La fonction mysqlnd_qc_get_query_trace_log() retourne une trace permettant d'aider dans cette tâche.
La collecte d'une trace de requête est une opération lente. Aussi, cette opération
est désactivée par défaut. La directive de configuration PHP
mysqlnd_qc.collect_query_trace
est utilisée pour l'activer. Les traces des fonctions contiennent une entrée pour
chaque requête émise avant l'appel à la fonction.
Exemple #1 Collecte d'une requête de traçage
mysqlnd_qc.enable_qc=1 mysqlnd_qc.collect_query_trace=1
<?php
/* connexion à MySQL */
$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");
/* quelques requêtes pour remplir les traces de requêtes */
for ($i = 0; $i < 2; $i++) {
$res = $mysqli->query("SELECT 1 AS _one FROM DUAL");
$res->free();
}
/* Affichage des traces */
var_dump(mysqlnd_qc_get_query_trace_log());
?>
Les exemples ci-dessus vont afficher :
array(2) { [0]=> array(8) { ["query"]=> string(26) "SELECT 1 AS _one FROM DUAL" ["origin"]=> string(102) "#0 qc.php(7): mysqli->query('SELECT 1 AS _on...') #1 {main}" ["run_time"]=> int(0) ["store_time"]=> int(25) ["eligible_for_caching"]=> bool(false) ["no_table"]=> bool(false) ["was_added"]=> bool(false) ["was_already_in_cache"]=> bool(false) } [1]=> array(8) { ["query"]=> string(26) "SELECT 1 AS _one FROM DUAL" ["origin"]=> string(102) "#0 qc.php(7): mysqli->query('SELECT 1 AS _on...') #1 {main}" ["run_time"]=> int(0) ["store_time"]=> int(8) ["eligible_for_caching"]=> bool(false) ["no_table"]=> bool(false) ["was_added"]=> bool(false) ["was_already_in_cache"]=> bool(false) } }
D'autres informations sont fournies dans les trâces. Parmi elles,
les horaires et l'origine de l'appel à la requête. La propriété origin
contient une trace du code pour identifier la source de la requête.
La profondeur de la trace du code peut être limitée avec la directive
de configuration PHP
mysqlnd_qc.query_trace_bt_depth
.
La profondeur par défaut est 3
.
Exemple #2 Définir la profondeur des traces avec l'option
de configuration ini mysqlnd_qc.query_trace_bt_depth
mysqlnd_qc.enable_qc=1 mysqlnd_qc.collect_query_trace=1
<?php
/* connexion à MySQL */
$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
/* quelques requêtes pour remplir les traces */
for ($i = 0; $i < 3; $i++) {
$res = $mysqli->query("SELECT id FROM test WHERE id = " . $mysqli->real_escape_string($i));
$res->free();
}
$trace = mysqlnd_qc_get_query_trace_log();
$summary = array();
foreach ($trace as $entry) {
if (!isset($summary[$entry['query']])) {
$summary[$entry['query']] = array(
"executions" => 1,
"time" => $entry['run_time'] + $entry['store_time'],
);
} else {
$summary[$entry['query']]['executions']++;
$summary[$entry['query']]['time'] += $entry['run_time'] + $entry['store_time'];
}
}
foreach ($summary as $query => $details) {
printf("%45s: %5dms (%dx)\n",
$query, $details['time'], $details['executions']);
}
?>
Les exemples ci-dessus vont afficher :
DROP TABLE IF EXISTS test: 0ms (1x) CREATE TABLE test(id INT): 0ms (1x) INSERT INTO test(id) VALUES (1), (2), (3): 0ms (1x) SELECT id FROM test WHERE id = 0: 25ms (1x) SELECT id FROM test WHERE id = 1: 10ms (1x) SELECT id FROM test WHERE id = 2: 9ms (1x)