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

<?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);
?>
<?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();
?>
<?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);
}
?>
<?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.

LoadingChargement en cours