Переходный процесс, не работающий для пользовательских циклов


Я работаю над темой WordPress. Поскольку мне нужно отображать избранные сообщения, связанные сообщения, некоторые виджеты с последними сообщениями и так далее, мне нужно использовать несколько пользовательских циклов. Из-за этого также увеличилось количество запросов к базе данных.

В попытке оптимизировать тему для повышения производительности я наткнулся на http://codex.wordpress.org/Transients_API , что кажется хорошим способом кэширования циклов, которые мне не нужно обновлять на каждой странице перезагрузить.

Пока все было хорошо, я использовал переходный процесс для wp_nav_menu, и он работал так, как должен. Мне удалось немного уменьшить количество запросов к бд.

Проблема возникла, когда я попытался использовать переходный процесс для пользовательских циклов.

Переходный процесс сохранен. Я могу получить временное значение. Единственная проблема заключается в том, что количество запросов к базе данных, по-видимому, значительно выше, чем при использовании WP_Query без переходного процесса.

Вот мой пользовательский цикл:

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();

В код, используемый для отображения количества запросов к базе данных и времени выполнения, выглядит следующим образом:

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

Используя плагин отладки запросов, я вижу, что update_meta_cache() генерирует множество запросов.

Я не могу объяснить, почему количество запросов к базе данных увеличивается, а не уменьшается, и почему это работает для меню, но не для пользовательских циклов. Может быть, я что-то упустил. Любая помощь будет оценена по достоинству.

Author: Marius, 2014-09-08

2 answers

Я действительно работал над сообщением вчера (проверьте его здесь ) и столкнулся с той же проблемой. Я также новичок в Переходном API, никогда с ним не работал:-).

Проблема здесь в том, что для определенного цикла вам нужно использовать определенное значение вне вашего переходного процесса. Вы просто сохраняете неправильные значения, и из-за этого вы получаете эти перегрузки бд.

Чтобы объяснить, вот часть кода из ответа, который я получил упоминаемый. Мне нужно создать список категорий с заголовками сообщений, относящихся к этим категориям. Для этого я запускаю свой пользовательский запрос, а затем использую значение $q для создания своего списка

    $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();

Это дает мне 6 queries in 0.06348 seconds.

Хорошо, если вы посмотрите на пример из кодекса, вы должны поместить свой new WP_Query результат в переходный процесс. Если я это сделаю, результаты будут совершенно неуместными

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


?>

С приведенным выше кодом мои результаты выглядят так 31 queries in 0.19141 seconds. Это на 25 запросов больше и занимает примерно на 0,13 секунды больше. Причина этого в том, что для каждого сообщения Wordpress необходимо повторно просматривать базу данных, чтобы получить категории, к которым относится сообщение, так как это не хранится в вашем временном хранилище. 25 дополнительных запросов - это количество записей в моей базе данных. Итак, вы видите, что на самом деле вы потратили впустую много ресурсов, храня неверную информацию. Мне не нужна информация из new WP_Query, но результат/значение из $q

Итак, чтобы правильно использовать переходные процессы, вы должны хранить правильные значения, которые вам нужны. Для этого мне нужно добавить мой полный запрос в переходный процесс, чтобы убедиться, что он выполняется только один раз, и именно тогда создается переходный процесс. После этого пользовательский запрос больше не нужен и является избыточным, единственное, что нужно сохранить и что мне сейчас нужно, - это значение $q. Итак, вот как изменяется запрос, чтобы удалить пользовательский запрос после создания переходного процесса и сохранить только значение $q

Просто чтобы отметить, я изменил свои временные имена вместе с способ просто для целей тестирования, чтобы показать время и запросы. Также обратите внимание, что при создании вашего переходного процесса вам необходимо использовать значение (в данном случае $q), которое вам нужно сохранить

 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 );
}

Это дает мне 2 queries in 0.00195 seconds. Вы видите, как я теперь эффективно использую переходные процессы. $q, который представляет собой массив из множества значений, теперь доступен для создания моего списка, и для достижения моей цели мне потребовалось всего 2 попадания в бд

Я надеюсь, что все это имеет смысл

 3
Author: Pieter Goosen, 2017-04-13 12:37:42

В вашем коде 3 проблемы

  1. Вы используете один запрос БД для сохранения другого запроса БД. Вы запрашиваете временное значение вместо таблицы post, которое может быть или не быть быстрее, но вы не экономите штраф за связь с базой данных.

  2. Вы не должны хранить объекты в переходных процессах или опциях. Согласно значениям документации, должны быть только скаляры, что может быть причиной сбоя get_transient в вашем коде. Одна из важных частей из того, что делает wp_query, что вы пропускаете, то, что может повлиять на производительность остальной части вашего кода, - это заполнение кэша путем хранения возвращенных объектов post в кэше (кэш в этом контексте - это кратковременный кэш за сеанс)

  3. Правильный способ кэширования - это кэширование сгенерированного HTML. Ваш код пытается сохранить один запрос, но вы сэкономите еще 40, если кэшируете HTML

 0
Author: Mark Kaplun, 2014-09-08 13:54:29