PHP 8.0.6 Released!

Mise en cache des requêtes

Il y a 4 façons de mettre en cache une requête.

  • Utiliser une astuce SQL pour chaque requête
  • L'utilisation fourni une fonction de rappel pour prise de décision pour chaque requête, par exemple, en utilisant la fonction mysqlnd_qc_is_select()
  • Utilisation de la fonction mysqlnd_set_cache_condition() pour des règles automatiques pour chaque requête
  • Utilisation de la directive mysqlnd_qc.cache_by_default = 1 pour mettre en cache toutes les requêtes aveuglément

L'utilisation d'astuce SQL et de la directive de configuration mysqlnd_qc.cache_by_default = 1 sont expliquées ci-dessous. Reportez-vous à la documentation sur la fonction mysqlnd_qc_is_select() pour une description de l'utilisation d'une fonction de rappel et à la documentation sur la fonction mysqlnd_qc_set_cache_condition() sur la façon pour définir des règles automatiques pour la mise en cache.

Une astuce SQL est un commentaire standard SQL. Comme tout commentaire SQL, il sera ignoré par la base de données. Une requête est considérée éligible à la mise en cache si elle commence par une astuce SQL activant la mise en cache, ou si c'est une requête de type SELECT.

Une requête individuelle qui doit être mise en cache doit commencer avec l'astuce SQL /*qc=on*/. Il est recommandé d'utiliser la constante PHP MYSQLND_QC_ENABLE_SWITCH au lieu d'utiliser la chaîne ci-dessus.

  • non éligible pour la mise en cache, et non mise en cache : INSERT INTO test(id) VALUES (1)

  • non éligible à la mise en cache et non mise en cache : SHOW ENGINES

  • éligible à la mise en cache, mais non mise en cache : SELECT id FROM test

  • éligible à la mise en cache et mise en cache : /*qc=on*/SELECT id FROM test

L'exemple avec la chaîne de requête SELECT est préfixé avec l'astuce SQL MYSQLND_QC_ENABLE_SWITCH pour active la mise en cache de la requête. L'astuce SQL doit être fournie au tout début de la chaîne de requête pour activer la mise en cache.

Exemple #1 Utilisation de l'astuce SQL MYSQLND_QC_ENABLE_SWITCH

mysqlnd_qc.enable_qc=1
<?php
/* Connexion, création et peuplement de la table test */
$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)");

/* Sera mis en cache en raison de la présence de l'astuce SQL */
$start microtime(true);
$res $mysqli->query("/*" MYSQLND_QC_ENABLE_SWITCH "*/" "SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
printf("Durée de la requête non mise en cache : %.6fs\n"microtime(true) - $start);

/* Récupération depuis le cache */
$start microtime(true);
$res $mysqli->query("/*" MYSQLND_QC_ENABLE_SWITCH "*/" "SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
printf("Durée de la requête mise en cache : %.6fs\n"microtime(true) - $start);
?>

Les exemples ci-dessus vont afficher :

array(1) {
  ["id"]=>
  string(1) "1"
}
Durée de la requête non mise en cache : 0.000740s
array(1) {
  ["id"]=>
  string(1) "1"
}
Durée de la requête mise en cache : 0.000098s

Si rien de plus n'est configuré, comme c'est le cas dans l'exemple de démarrage rapide, le plugin utilisera le gestionnaire de stockage interne default. Le gestionnaire de stockage default utilise un processus mémoire pour stocker une entrée du cache. Suivant le modèle de déployement PHP, un processus PHP peut servir une ou plusieurs requêtes web. Veuillez consulter le manuel de votre serveur web pour plus de détails. Ces détails ne feront aucune différence dans les exemples de cette section.

Le plugin de mise en cache de requêtes va mettre en cache toutes les requêtes si la chaîne commence par une astuce SQL qui active ou non la mise en cache, si la directive de configuration PHP mysqlnd_qc.cache_by_default vaut 1. La configuration mysqlnd_qc.cache_by_default est évaluée par le coeur du plugin de mise en cache de requêtes. Aussi, ni le coeur du plugin, ni un gestionnaire de stockage défini par l'utilisateur ne peuvent écraser cette configuration.

L'astuce SQL /*qc=off*/ peut être utilisée pour désactiver la mise en cache d'une requête si mysqlnd_qc.cache_by_default = 1. Il est recommandé d'utiliser la constante PHP MYSQLND_QC_DISABLE_SWITCH au lieu de la valeur litérale.

Exemple #2 Utilisation de l'astuce SQL MYSQLND_QC_DISABLE_SWITCH

mysqlnd_qc.enable_qc=1
mysqlnd_qc.cache_by_default=1
<?php
/* Connexion, création et peuplement de la table test */
$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)");

/* Sera mise en cache malgré le fait qu'aucune astuce SQL ne soit présente,
car mysqlnd_qc.cache_by_default = 1*/
$res $mysqli->query("SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();

$mysqli->query("DELETE FROM test WHERE id = 1");

/* Récupération depuis le cache - aucune invalidation automatique, et donc, toujours valide ! */
$res $mysqli->query("SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();

/* Non présente dans le cache - la requête ne doit pas être mise en cache en raison de
la présence de l'astuce SQL */
$res $mysqli->query("/*" MYSQLND_QC_DISABLE_SWITCH "*/SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
?>

Les exemples ci-dessus vont afficher :

array(1) {
  ["id"]=>
  string(1) "1"
}
array(1) {
  ["id"]=>
  string(1) "1"
}
NULL

PECL/mysqlnd_qc ne mettra pas en cache les requêtes pour lesquelles au moins une colonne du jeu de résultats ne contient pas le nom de la table dans ses méta-données par défaut. C'est habituellement le cas pour les colonnes provenant de fonctions SQL comme NOW() ou LAST_INSERT_ID(). La politique vise à éviter les pièges, si la mise en cache est utilisée par défaut.

Exemple #3 Exemple montrant les types de requêtes non mis en cache

mysqlnd_qc.enable_qc=1
mysqlnd_qc.cache_by_default=1
<?php
/* Connexion, création et peuplement de la table test */
$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)");

for (
$i 0$i 3$i++) {

  
$start microtime(true);

  
/* Note : la requête ne sera pas mise en cache car NOW() est utilisé */
  
$res $mysqli->query("SELECT id, NOW() AS _time FROM test");
  
$row $res->fetch_assoc();

  
/* Affichage des résultats */
  
var_dump($row);

  
printf("Durée d'exécution : %.6fs\n"microtime(true) - $start);

  
/* On attend une seconde */
  
sleep(1);
}
?>

Les exemples ci-dessus vont afficher :

array(2) {
  ["id"]=>
  string(1) "1"
  ["_time"]=>
  string(19) "2012-01-11 15:43:10"
}
Durée d'exécution : 0.000540s
array(2) {
  ["id"]=>
  string(1) "1"
  ["_time"]=>
  string(19) "2012-01-11 15:43:11"
}
Durée d'exécution : 0.000555s
array(2) {
  ["id"]=>
  string(1) "1"
  ["_time"]=>
  string(19) "2012-01-11 15:43:12"
}
Durée d'exécution : 0.000549s

Il est possible d'activer la mise en cache pour toutes les requêtes, y compris celles qui contiennent des colonnes dans leur jeu de résultats pour lesquelles MySQL rapporte aucune table, comme la requête de l'exemple ci-dessus. Définissez la directive de configuration comme ceci mysqlnd_qc.cache_no_table = 1 pour activer la mise en cache de telle requête. Notez la différence dans les durées mesurées de l'exemple ci-dessus et de l'exemple ci-dessous.

Exemple #4 Activation du cache pour toutes les requêtes en utilisant l'option de configuration ini mysqlnd_qc.cache_no_table

mysqlnd_qc.enable_qc=1
mysqlnd_qc.cache_by_default=1
mysqlnd_qc.cache_no_table=1
<?php
/* Connexion, création et peuplement de la table test */
$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)");

for (
$i 0$i 3$i++) {

  
$start microtime(true);

  
/* Note : la requête ne sera pas mise en cache car NOW() est utilisé */
  
$res $mysqli->query("SELECT id, NOW() AS _time FROM test");
  
$row $res->fetch_assoc();

  
/* Affichage des résultats */
  
var_dump($row);

  
printf("Durée d'exécution : %.6fs\n"microtime(true) - $start);

  
/* On attend une seconde */
  
sleep(1);
}
?>

Les exemples ci-dessus vont afficher :

array(2) {
  ["id"]=>
  string(1) "1"
  ["_time"]=>
  string(19) "2012-01-11 15:47:45"
}
Total time: 0.000546s
array(2) {
  ["id"]=>
  string(1) "1"
  ["_time"]=>
  string(19) "2012-01-11 15:47:45"
}
Durée d'exécution : 0.000187s
array(2) {
  ["id"]=>
  string(1) "1"
  ["_time"]=>
  string(19) "2012-01-11 15:47:45"
}
Durée d'exécution : 0.000167s

Note:

Bien que mysqlnd_qc.cache_no_table = 1 a été créé pour une utilisation avec mysqlnd_qc.cache_by_default = 1, il y est lié. Le plugin va évaluer la directive mysqlnd_qc.cache_no_table à chaque fois qu'une requête est prête à être mise en cache, sans tenir compte de l'activation du cache en utilisant une astuce SQL ou toute autre mesure.

add a note add a note

User Contributed Notes 1 note

up
3
laurent at pele dot org
3 years ago
This query cache feature enhances a lot performance of my web site, unfortunately, installation dll are available on windows only up to version 5.5. For example, if I use it on php 5.6, there is an error message on startup saying it is not compatible
To Top