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.
Document créé le 30/01/2003, dernière modification le 26/10/2018
Source du document imprimé : https://www.gaudry.be/php-rf-mysqlnd-qc.quickstart.caching.html
L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.
Références
Ces références et liens indiquent des documents consultés lors de la rédaction de cette page, ou qui peuvent apporter un complément d'information, mais les auteurs de ces sources ne peuvent être tenus responsables du contenu de cette page.
L'auteur de ce site est seul responsable de la manière dont sont présentés ici les différents concepts, et des libertés qui sont prises avec les ouvrages de référence. N'oubliez pas que vous devez croiser les informations de sources multiples afin de diminuer les risques d'erreurs.