Almacenar consultas en la caché
Hay cuatro maneras de desencadenar el almacenamiento en caché de una consulta.
-
Usar sugerencias SQL en función de cada consulta
-
Llamadas de retorno porporcionadas por el usuario para decidir en función de cada consulta, por ejemplo, usando mysqlnd_qc_is_select()
-
mysqlnd_set_cache_condition() para reglas basadas en decisiones automáticas en cada consulta
-
mysqlnd_qc.cache_by_default = 1
para almacenar en caché todas las consultas a ciegas
El uso de las sugerencias SQL y de
mysqlnd_qc.cache_by_default = 1
se expilca más abajo. Por vafor, consulte la referenca de la función
mysqlnd_qc_is_select() para una descripción del uso de una llamada de retorno, y de
mysqlnd_qc_set_cache_condition() sobre cómo establecer reglas para el almacenamiento
automático en caché.
Una sugerencia SQL es un comentario que sigue los
estándares. Como comentario de SQL, es ignorado por la base de datos. Una consulta es considerada
candidata para su almacenamiento en caché si comienza con la sugerencia SQL que habilita dicho almacenamiento
o si es una sentencia SELECT
.
Una consulta individual que debiera ser almacenada debe comenzar con la sugerencia SQL
/*qc=on*/
. Se recomienda usar la constante de PHP
MYSQLND_QC_ENABLE_SWITCH
en lugar del valor de cadena.
-
no candidata para su almacenamiento en caché y no almacenada: INSERT INTO test(id) VALUES (1)
-
no candidata para su almacenamiento en caché y no almacenada: SHOW ENGINES
-
candidata para su almacenamiento en caché pero no almacenada: SELECT id FROM test
-
candidata para su almacenamiento y almacenada: /*qc=on*/SELECT id FROM test
Las sentencias SELECT
del ejemplo están prefijadas con la sugerencia SQL
MYSQLND_QC_ENABLE_SWITCH
para habilitar su almacenamiento en caché. La sugerencia SQL debe colocarse al
comienzo de la cadena de consulta para habilitar el almacenamiento en caché.
Ejemplo #1 Usar la sugerencia SQL MYSQLND_QC_ENABLE_SWITCH
<?php
/* Conectar, crear y rellenar la tabla test */
$mysqli = new mysqli("host", "usuario", "contraseña", "esquema", "puerto", "socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2)");
/* Será almacenada en caché debido a la sugerencia SQL */
$inicio = microtime(true);
$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
printf("Tiempo total de consulta no almacenada: %.6fs\n", microtime(true) - $inicio);
/* Coincidencia con la caché */
$inicio = microtime(true);
$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
printf("Tiempo total de consulta almacenada: %.6fs\n", microtime(true) - $inicio);
?>
El resultado de los ejemplos
sería algo similar a:
array(1) {
["id"]=>
string(1) "1"
}
Tiempo total de consulta no almacenada: 0.000740s
array(1) {
["id"]=>
string(1) "1"
}
Tiempo total de consulta almacenada: 0.000098s
Si no se configura nada más, como es el caso del ejemplo de esta guía rápida,
el complemento usará en gestor de almacenamiento interno default
.
El gestor de almacenamiento default
utiliza la memoria del proceso para mantener una entrada de la caché.
Dependiendo del modelo de desarrollo de PHP, un proceso de PHP podría servir una o más
peticiones web. Por favor, consulte el manual del servidor web para más detalles.
Los detalles son irrelevantes para los ejemplos dados en esta guía rápida.
El complemento de caché de consultas almacenará todas las consultas sin considerar si
la cadena de consulta comienza con la sugerencia SQL que habilita dicho almacenamiento,
si la directiva de configuración de PHP
mysqlnd_qc.cache_by_default
está establecida a 1
. El ajuste
mysqlnd_qc.cache_by_default
es evaluado por el núcleo del complemento de caché de consultas.
Ni el gestor de almacenamiento interno ni uno definido por el usuario pueden sobrescribir el ajuste.
La sugerencia SQL /*qc=off*/
se puede usar para deshabilitar el almacenamiento en caché
de consultas individuales si
mysqlnd_qc.cache_by_default = 1
.
Se recomienda usar la constante de PHP
MYSQLND_QC_DISABLE_SWITCH
en lugar del valor de cadena.
Ejemplo #2 Usar la sugerencia SQL MYSQLND_QC_DISABLE_SWITCH
mysqlnd_qc.enable_qc=1
mysqlnd_qc.cache_by_default=1
<?php
/* Conectar, crear y rellenar la tabla test */
$mysqli = new mysqli("host", "usuario", "contraseña", "esquema", "puerto", "socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2)");
/* Será almacenada aunque no esté presente ninguna sugerencia SQL ya que 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");
/* Coincidencia con la caché - ¡sin invalidación automática y aún válida! */
$res = $mysqli->query("SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
/* No coincide con la caché - la consulta no debe almacenarse debido a la sugerencia SQL */
$res = $mysqli->query("/*" . MYSQLND_QC_DISABLE_SWITCH . "*/SELECT id FROM test WHERE id = 1");
var_dump($res->fetch_assoc());
$res->free();
?>
El resultado de los ejemplos sería:
array(1) {
["id"]=>
string(1) "1"
}
array(1) {
["id"]=>
string(1) "1"
}
NULL
PECL/mysqlnd_qc prohíbe el almacenamiento en la caché de sentencias donde al menos una columna del conjunto
de resultados de dichas sentencias no muestren el nombre de la tabla en sus metadatos de forma predeterminada.
Éste normalmente es el caso para las columnas originadas desde funciones SQL tales como
NOW()
o LAST_INSERT_ID()
. La política
se dirige a prevenir fallos si se usa el almacenamiento por omisión.
Ejemplo #3 Ejemplo que muestra qué tipos de sentencias no son almacenadas en la caché
mysqlnd_qc.enable_qc=1
mysqlnd_qc.cache_by_default=1
<?php
/* Conectar, crear y rellenar la tabla test */
$mysqli = new mysqli("host", "usuario", "contraseña", "esquema", "puerto", "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++) {
$inicio = microtime(true);
/* Nota: la sentencia no será almacenada debido al uso de NOW() */
$res = $mysqli->query("SELECT id, NOW() AS _time FROM test");
$fila = $res->fetch_assoc();
/* volcar resultados */
var_dump($fila);
printf("Tiempo total: %.6fs\n", microtime(true) - $inicio);
/* pausar durante un segundo */
sleep(1);
}
?>
El resultado de los ejemplos
sería algo similar a:
array(2) {
["id"]=>
string(1) "1"
["_time"]=>
string(19) "2012-01-11 15:43:10"
}
Tiempo total: 0.000540s
array(2) {
["id"]=>
string(1) "1"
["_time"]=>
string(19) "2012-01-11 15:43:11"
}
Tiempo total: 0.000555s
array(2) {
["id"]=>
string(1) "1"
["_time"]=>
string(19) "2012-01-11 15:43:12"
}
Tiempo total: 0.000549s
Es posible habilitar el almacenamiento en caché para todas las sentecias incluyendo aquellas
que tienen columnas en su conjunto de resultados para las cuales MySQL no notifica una tabla, como
la sentencia del ejemplo. Se ha de establecer
mysqlnd_qc.cache_no_table = 1
para habilitar el almacenamiento en caché de tales sentencias. Por favor, observe la diferencia en los
tiempos medidos para los ejemplos de arriba y de abajo.
Ejemplo #4 Habilitar el almacenamiento en caché de todas las sentencias usando el ajuste ini mysqlnd_qc.cache_no_table
mysqlnd_qc.enable_qc=1
mysqlnd_qc.cache_by_default=1
mysqlnd_qc.cache_no_table=1
<?php
/* Conectar, crear y rellenar la tabla test */
$mysqli = new mysqli("host", "usuario", "contraseña", "esquema", "puerto", "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++) {
$inicio = microtime(true);
/* Nota: la sentencia no será almacenada debido al uso de NOW() */
$res = $mysqli->query("SELECT id, NOW() AS _time FROM test");
$fila = $res->fetch_assoc();
/* volcar resultados */
var_dump($fila);
printf("Tiempo total: %.6fs\n", microtime(true) - $inicio);
/* pausar durante un segundo */
sleep(1);
}
?>
El resultado de los ejemplos
sería algo similar a:
array(2) {
["id"]=>
string(1) "1"
["_time"]=>
string(19) "2012-01-11 15:47:45"
}
Tiempo total: 0.000546s
array(2) {
["id"]=>
string(1) "1"
["_time"]=>
string(19) "2012-01-11 15:47:45"
}
Tiempo total: 0.000187s
array(2) {
["id"]=>
string(1) "1"
["_time"]=>
string(19) "2012-01-11 15:47:45"
}
Tiempo total: 0.000167s
Nota:
Aunque mysqlnd_qc.cache_no_table = 1
haya sido creado para usarlo con
mysqlnd_qc.cache_by_default = 1
está vilculado a él. El complemento evaluará
mysqlnd_qc.cache_no_table
siempre que se vaya a almacenar una consulta, sin importar si el almacenameinto en caché ha sido habilitado
usando una sugerencia SQL o cualquier otra medida.