web-dev-qa-db-fra.com

Transitoire ne fonctionne pas pour les boucles personnalisées

Je travaille sur un thème WordPress. Étant donné que je dois afficher les publications en vedette, les publications connexes, certains widgets avec des publications récentes, etc., je dois utiliser plusieurs boucles personnalisées. De ce fait, le nombre de requêtes de base de données a également augmenté.

Dans une tentative d’optimisation du thème pour de meilleures performances, j’ai rencontré http://codex.wordpress.org/Transients_API , ce qui semble être un bon moyen de cache les boucles que je n'ai pas besoin de mettre à jour à chaque rechargement de page.

Jusqu'ici tout va bien, j'ai utilisé transitoire pour wp_nav_menu et cela a fonctionné comme il se doit. J'ai réussi à diminuer un peu le nombre de requêtes de base de données.

Le problème est survenu lorsque j'ai essayé d'utiliser le transitoire pour des boucles personnalisées.

Le transitoire est enregistré. Je peux obtenir la valeur transitoire. Le seul problème est que le nombre de requêtes dans la base de données semble être considérablement plus élevé que lorsque vous utilisez WP_Query sans transitoire.

Voici ma boucle personnalisée:

if( false === ( $loop = get_transient('featured') ) ) {
    $loop = new WP_Query( array( 'posts_per_page' => 20 ) );
    set_transient('featured', $loop, 60 * MINUTE_IN_SECONDS);
}

if( $loop->have_posts() ) :

    while( $loop->have_posts() ) : $loop->the_post();

        the_title();
        the_post_thumbnail('thumb');

    endwhile;

endif;
wp_reset_postdata();

Le code utilisé pour afficher le nombre de requêtes de base de données et le temps d'exécution est le suivant:

<?php echo get_num_queries(); ?> queries in <?php timer_stop(1); ?> seconds.

En utilisant un plugin de débogage de requête, je vois que update_meta_cache () génère beaucoup de requêtes.

Je ne peux pas expliquer pourquoi le nombre de requêtes de base de données augmente au lieu de diminuer et pourquoi cela fonctionne pour les menus, mais pas pour les boucles personnalisées. Peut-être que j'ai raté quelque chose. Toute aide est appréciée.

2
Marius

En fait, j’ai travaillé sur un article hier (regardez-le ici ) et vous êtes frappé par le même problème. Je suis également nouveau sur l'API Transient , je n'ai jamais travaillé avec :-).

Le problème ici est que pour une boucle spécifique, vous devez utiliser une certaine valeur en dehors de votre transitoire. Vous stockez simplement les mauvaises valeurs et, pour cette raison, vous obtenez cette surcharge de hits de base de données.

Pour expliquer, voici une partie du code de la réponse à laquelle j'ai fait référence. J'ai besoin de créer une liste de catégories avec des titres d'articles appartenant à ces catégories. Pour ce faire, j'exécute ma requête personnalisée, puis utilise la valeur $q pour créer ma liste.

    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

Cela me donne 6 queries in 0.06348 seconds.

OK, si vous regardez ce que donne l'exemple du codex, vous devriez mettre votre résultat new WP_Query en transitoire. Si je le fais, le résultat est totalement détraqué

<?php
if( false === ( $query = get_transient('custom_query') ) ) {
    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 
 set_transient('custom_query', $query, 60 * MINUTE_IN_SECONDS);
}
    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();


?>

Avec le code ci-dessus, mes résultats ressemblent à ceci 31 queries in 0.19141 seconds. Cela représente 25 requêtes de plus et prend environ 0,13 seconde de plus. La raison en est que, pour chaque publication, Wordpress doit revisiter la base de données pour récupérer les catégories auxquelles la publication appartient, car elles ne sont pas stockées de manière transitoire. 25 requêtes supplémentaires correspondent au nombre de messages dans ma base de données. Vous voyez donc que vous avez effectivement gaspillé beaucoup de ressources en stockant les informations erronées. Je n'ai pas besoin des informations du new WP_Query, mais du résultat/de la valeur de $ q

Donc, pour utiliser correctement les transitoires, vous devez stocker les valeurs correctes que vous recherchez. Pour ce faire, je dois ajouter ma requête complète à un transitoire afin de m'assurer qu'elle ne soit exécutée qu'une seule fois, c'est-à-dire à la création du transitoire. Après cela, la requête personnalisée n'est plus nécessaire et est redondante. La seule chose qui doit être stockée et que je recherche maintenant est la valeur $q. Ainsi, voici comment la requête est modifiée pour supprimer la requête personnalisée après la création du transitoire et pour enregistrer uniquement la valeur de $q

Juste pour noter, j'ai changé mes noms de passager en cours de route, juste à des fins de test pour afficher les temps et les requêtes. Notez également que lors de la création de votre transitoire, vous devez utiliser la valeur (dans ce cas, $q), vous devez enregistrer .

 if ( false === ( $q = get_transient( 'category_list' ) ) ) {

    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

set_transient( 'category_list', $q, 12 * HOUR_IN_SECONDS );
}

Cela me donne 2 queries in 0.00195 seconds. Vous voyez comment je me sers efficacement des transitoires. $q qui est un tableau de plusieurs valeurs, est maintenant disponible pour créer ma liste, et cela ne m'a coûté que 2 hits de base de données pour atteindre mon objectif

J'espère que tout cela a du sens

2
Pieter Goosen

Votre code a 3 problèmes

  1. vous utilisez une requête de base de données pour enregistrer une autre requête de base de données. Vous interrogez une valeur transitoire à la place de la table post qui peut être plus rapide ou non, mais vous ne sauvegardez pas la pénalité liée à la communication avec la base de données.

  2. Vous ne devez pas stocker d'objets dans des transitoires ou des options. Selon les valeurs de la documentation, il ne devrait exister que des scalaires, ce qui pourrait expliquer l'échec de get_transient dans votre code. Une des parties importantes de ce que wp_query fait que vous ignorez par ce qui pourrait influer sur les performances du reste de votre code est l’amorçage du cache en stockant les objets post renvoyés dans le cache (cache dans ce contexte est le cache de courte durée par session)

  3. la bonne façon de mettre en cache consiste à mettre en cache le code HTML généré. Votre code tente de sauvegarder une requête, mais vous en enregistrerez 40 de plus si vous cachez le code HTML.

0
Mark Kaplun