web-dev-qa-db-fra.com

une boucle de publication provoque des requêtes DB wp_users et wp_usermeta DB pour chaque utilisateur

En continuant ma question précédente : Ma boucle de publication génère 2 requêtes par publication:

SELECT * FROM wp_users WHERE ID = '53'
require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), include('/themes/BT/search.php'), the_post, WP_Query->the_post, WP_Query->setup_postdata, get_userdata, get_user_by, WP_User::get_data_by #20 (0.1ms)
SELECT user_id, meta_key, meta_value FROM wp_usermeta WHERE user_id IN (53) ORDER BY umeta_id ASC
require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), include('/themes/BT/search.php'), the_post, WP_Query->the_post, WP_Query->setup_postdata, get_userdata, get_user_by, WP_User->init, WP_User->for_blog, WP_User->_init_caps, get_user_meta, get_metadata, update_meta_cache #21 (0.2ms)

Cela se produit même après avoir réduit le code du modèle à une simple boucle:

if ( have_posts() ) : while ( have_posts() ) : the_post();
        echo $post->ID . "<br />";
    endwhile;
endif;
  • Est-ce attendu?
  • Wordpress n'est-il pas censé obtenir toutes les données utilisateur en une seule requête?
1
Jonathan

Alors que WordPress est devenu très bon en cache de base de données pour les boucles (vignettes, méta, termes), il ne met pas en cache les utilisateurs (auteurs).

Ainsi, si vous avez 5 auteurs différents dans toutes les publications de votre boucle, vous obtenez 10 requêtes (1 pour l'objet utilisateur, 1 pour la réserve de méta-cache de l'utilisateur). C'est grâce à WP_Query::setup_postdata() (appelé par the_post()) - cette ligne:

$authordata = get_userdata($post->post_author);

Si l'auteur de l'article est déjà dans le cache, ne touchez pas la base de données. C'est pourquoi vous pourriez avoir 100 éléments en boucle dans votre boucle provenant de 5 auteurs et que vous ne disposeriez que de 10 requêtes supplémentaires.

Pour mettre en cache de manière préventive tous les utilisateurs de la boucle et ne jamais avoir que 2 requêtes, quel que soit le nombre d'auteurs différents:

function wpse_203912_the_posts( $posts, $wp_query ) {
    if ( $wp_query->is_main_query() ) { // Remove this condition if you want to cache users whenever anywhere queries posts
        $user_ids = wp_list_pluck( $posts, 'post_author' );
        cache_users( $user_ids );
    }

    return $posts;
}

add_filter( 'the_posts', 'wpse_203912_the_posts', 10, 2 );

Le point positif de cache_users() est qu’elle ne frappe que la base de données pour les utilisateurs non mis en cache. Vous pouvez donc l’appeler de manière répétée sans vous inquiéter si vous avez déjà mis l’utilisateur en cache.

2
TheDeadMedic