¿Debo usar la API transitoria para almacenar cadenas u objetos HTML?

18

Supongamos que hay un complemento que muestra 20 publicaciones relacionadas (para cada publicación) con una consulta muy compleja. Y luego, utilizando los datos de esta consulta, crea un diseño HTML complejo. Además, debe tenerse en cuenta que el complemento es público y se puede instalar en cualquier servidor con cualquier configuración.

Algo como:

/* complex and large query */
$related_posts = get_posts( ... );

$html_output = '';
foreach($related_posts as $key => $item) {
     /* complex layout rendering logic (but not as slow as the previous query) */   
     $html_output .= ...;
}

Entonces mis preguntas son:

  • ¿Cuál es la forma más segura y correcta de almacenar en caché dichos datos?
  • ¿Debo usar la API transitoria para almacenar en caché la $related_postsmatriz o $html_outputcadena? Si voy a almacenar en caché la $html_ouputcadena, ¿alcanzará algún límite de tamaño máximo? ¿Debería quizás comprimirlo antes de guardarlo?
  • ¿Debo usar la API transitoria aquí?
Marvin3
fuente

Respuestas:

18

¿Debo usar la API transitoria aquí?

No.

En un archivo de instalación de WordPress, los transitorios se almacenan en la tabla wp_options, y solo se limpian durante las actualizaciones principales. Supongamos que tiene 50,000 publicaciones, eso es 50,000 filas adicionales en la tabla de opciones. Obviamente están configurados para cargar automáticamente = no, por lo que no va a consumir toda su memoria, pero hay otra advertencia.

El campo de carga automática en la tabla de opciones no tiene un índice, lo que significa que la llamada wp_load_alloptions()a realizará una exploración completa de la tabla. Cuantas más filas tenga, más tardará. Cuanto más a menudo escriba en la tabla de opciones, menos eficaces serán los cachés internos de MySQL.

Si los datos almacenados en caché están directamente relacionados con una publicación, es mejor que los almacene en la meta meta. Esto también le ahorrará una consulta cada vez que necesite mostrar el contenido almacenado en caché, porque los meta cachés posteriores (generalmente) se preparan durante la recuperación posterior en WP_Query.

Su estructura de datos para el metavalor puede variar, puede tener una marca de tiempo y realizar su consulta costosa si el valor en caché está desactualizado, al igual que se comportaría un transitorio.

Otro aspecto importante a tener en cuenta es que los transitorios de WordPress pueden ser volátiles en entornos con almacenamiento en caché de objetos persistente. Esto significa que si almacena sus datos almacenados en caché durante 24 horas de forma transitoria, no hay absolutamente ninguna garantía de que estará disponible en 23 horas, o 12, o incluso 5 minutos. El backend de la caché de objetos para muchas instalaciones es un almacén de valores clave en memoria como Redis o Memcached, y si no hay suficiente memoria asignada para adaptarse a los objetos más nuevos, los elementos más antiguos serán desalojados. Esta es una gran victoria para el enfoque de meta almacenamiento.

La invalidación también puede ser más inteligente, es decir, ¿por qué invalidas cachés de publicaciones relacionadas en X horas? ¿Es porque algún contenido ha cambiado? ¿Se ha agregado una nueva publicación? ¿Se ha asignado una nueva etiqueta? Dependiendo de su "consulta grande y compleja", puede optar por invalidar SOLAMENTE si sucede algo que va a alterar los resultados de su consulta.

¿Debo usar la API transitoria para almacenar en caché la matriz $ related_posts o la cadena $ html_output? Si voy a almacenar en caché la cadena $ html_ouput, ¿alcanzará algún límite de tamaño máximo? ¿Debería quizás comprimirlo antes de guardarlo?

Depende mucho del tamaño de su cadena, ya que esos son los datos que fluirán entre PHP, MySQL, etc. Deberá esforzarse mucho para alcanzar los límites de MySQL, pero por ejemplo, el límite predeterminado por objeto de Memcached es solo 1 mb.

¿Cuánto tiempo tarda realmente su "lógica de representación de diseño complejo"? Ejecútelo a través de un generador de perfiles para averiguarlo. Lo más probable es que sea muy rápido y nunca se convierta en un cuello de botella.

Si ese es el caso, sugeriría almacenar en caché las ID de las publicaciones. No los objetos WP_Post, porque contendrán el contenido completo de la publicación, sino solo una matriz de ID de publicación. Luego, utilice un WP_Querycon un post__inque dará como resultado una consulta MySQL muy rápida por clave primaria.

Dicho esto, si los datos necesarios por elemento son bastante simples, tal vez título, url de miniatura y enlace permanente, puede almacenar solo esos tres, sin la sobrecarga de un viaje de ida y vuelta adicional a MySQL, y sin la sobrecarga del almacenamiento en caché de HTML muy largo instrumentos de cuerda.

Wow, eso son muchas palabras, espero que ayude.

kovshenin
fuente
12

No todo el código WP es código público

Si vas a lanzar algo público, entonces todas las cosas que dijo kovshenin son perfectamente válidas.

Las cosas son diferentes si va a escribir código privado para usted o su empresa.

La memoria caché de objetos externos es un gran beneficio, en cualquier caso

Para configurar un caché de objetos persistentes externos es muy recomendable , cuando puede.

Todas las cosas que se dicen en la respuesta de kovshenin sobre los transitorios y MySQL son muy ciertas, y teniendo en cuenta que WP en sí y un montón de complementos hacen uso de la caché de objetos ... entonces la mejora del rendimiento que obtuvo, vale la pena el esfuerzo (pequeño) de configuración Un sistema de caché moderno como Redis o Memcached.

Los valores en caché pueden no estar allí: está bien

Además, sí, un caché de objetos externo no es confiable. Nunca debe confiar en el hecho de que hay un transitorio. Debe asegurarse de que funcione si el almacenamiento en caché no está donde debería estar.

El caché no es almacenamiento, el caché es caché.

Usar caché selectivamente

Ver este ejemplo:

function my_get_some_value($key) {
   // by default no cache when debug and if no external object_cache
   $defUse = ! (defined('WP_DEBUG') && WP_DEBUG) && wp_using_ext_object_cache();
   // make the usage of cache filterable
   $useCache = apply_filters('my_use_cache', $defUse);
   // return cached value if any
   if ($useCache && ($cached = get_transient($key))) {
     return $cached;
   }
   // no cached value, make sure your code works with no cache
   $value = my_get_some_value_in_some_expensive_way();
   // set cache, if allowed
   $useCache and set_transient($key, $value, HOUR_IN_SECONDS);

   return $value;
}

Con un código como este, en su sitio privado, el rendimiento del sitio puede mejorar mucho , especialmente si tiene muchos usuarios.

Tenga en cuenta que:

  • Por defecto, el caché no se usa cuando la depuración está activada, por lo que es de esperar en su entorno de desarrollo. Créeme, el caché puede hacer que la depuración sea un infierno
  • Por defecto, el caché tampoco se usa cuando WP no está configurado para usar un caché de objetos externo. Significa que todo el problema relacionado con MySQL no existe, porque no usas transitorios cuando usan MySQL. Una alternativa probablemente más fácil sería usar wp_cache_*funciones , de modo que si no se configura una memoria caché externa, la memoria caché se almacena en la memoria y la base de datos nunca está involucrada.
  • El uso de caché es filtrable, para manejar algunos casos extremos que puede encontrar

Sin escala web si no hay caché

No debe intentar resolver los problemas de velocidad con el caché. Si tienes problemas de velocidad, entonces debes repensar tu código.

Pero para escalar un sitio web a escala web, el caché es bastante necesario .

Y muchas veces (pero no siempre) fragmentan, el caché contextual es mucho más flexible y adecuado que el almacenamiento en caché de página completa agresivo.

Tus preguntas:

¿Debo usar la API transitoria aquí?

Depende .

¿Tu código consume muchos recursos? Si no, tal vez no hay necesidad de caché. Como se dijo, no es solo una cuestión de velocidad. Si su código se ejecuta rápido pero requiere un montón de CPU y memoria para un par de usuarios ... ¿qué sucede cuando tiene 100 o 1000 usuarios concurrentes?

Si te das cuenta de que el caché sería una buena idea ...

... y es código público: probablemente no . Puede considerar almacenar en caché de forma selectiva, como en mi ejemplo anterior en código público, pero generalmente es mejor si deja tales decisiones a los implementadores.

... y es un código privado: muy probablemente sí . Pero incluso para el código privado, almacenar en caché de forma selectiva sigue siendo algo bueno, por ejemplo para la depuración.

Recuerde, de todos modos, que las wp_cache_*funciones pueden darle acceso a la memoria caché sin el riesgo de contaminar la base de datos.

¿Debo usar la API transitoria para almacenar en caché la matriz $ related_posts o la cadena $ html_output?

Depende de muchas cosas. ¿Qué tan grandes son las cuerdas? ¿Qué caché externo estás usando? Si va a almacenar en caché las publicaciones, almacenar una ID como matriz puede ser una buena idea, consultar un número decente de publicaciones por su ID es bastante rápido.

Notas finales

La API transitoria es probablemente una de las mejores cosas de WordPress. Gracias a los complementos que puede encontrar para cualquier tipo de sistemas de caché, se convierte en una estúpida API simple para una gran cantidad de software que puede funcionar bajo el capó.

Fuera de WordPress, es muy difícil encontrar esa abstracción que funciona de forma inmediata con un montón de sistemas de almacenamiento en caché diferentes, y le permite cambiar de un sistema a otro sin ningún esfuerzo.

Rara vez me oyes decir que WordPress es mejor que otras cosas modernas, pero la API transitoria es una de las pocas cosas que extraño cuando no trabajo con WordPress.

Seguramente el caché es duro, no resuelve problemas de código y no es una bala de plata, pero es algo que necesita para construir un sitio de alto tráfico que funcione.

La idea de WordPress de usar una tabla MySQL poco optimizada para hacer caché es bastante loca, pero no es mejor mantenerse alejado del caché solo porque WordPress, por defecto, lo hace.

Solo necesita comprender cómo funcionan las cosas y luego hacer su elección.

gmazzap
fuente
2

Las respuestas anteriores ya han resaltado el obligatorio " Depende ", con lo cual estoy totalmente de acuerdo.

Sin embargo, me gustaría agregar una recomendación, basada en cómo " supongo " que esto se haría mejor en el escenario que está describiendo anteriormente.

No usaría Transitorios en ese caso, sino Post Meta , debido a una ventaja que tiene este último: Control .

Como necesita almacenar en caché los datos por publicación, la cantidad de datos que almacenará en caché depende de la cantidad de publicaciones y crecerá con el tiempo. Una vez que supere un cierto número de publicaciones, puede alcanzar los límites de memoria que su caché de objetos puede usar, y comenzará a borrar los datos almacenados previamente en la memoria caché antes de que expiren. Esto podría conducir a una situación, donde tiene una gran afluencia de visitantes, donde cada visitante activará el "SQL demasiado complejo" en cada solicitud de página, y su sitio se atascará por completo.

Si almacena en caché los datos en su Post Meta, no solo puede controlar cómo se almacenan y recuperan, sino que también puede controlar exactamente cómo se actualizan. Agregaría un trabajo cron para esto que se ejecuta solo en períodos de tiempo donde hay menos o ningún tráfico hacia el sitio. Por lo tanto, la "consulta lenta" nunca es encontrada por usuarios reales del sitio, e incluso puede precargarla, de modo que el trabajo ya esté hecho cuando llegue el primer visitante.

¡Tenga en cuenta que todo el almacenamiento en caché es una compensación! Es por eso que la respuesta habitual es "depende". y por qué no hay un "santo grial de almacenamiento en caché".

Alain Schlesser
fuente