Как оптимизировать WP сайт для миллионов постов

19

Я работаю над сайтом для компании, которая, скорее всего, будет создавать миллионы постов через пользовательский тип поста. Это молитвы, поэтому в основном пользователь на переднем крае просто отправляет короткую фразу через форму. Все, что заботится о компании, - это содержание публикации и дата публикации. Сайт еще даже не запущен, и у него уже есть более 120 000 сообщений, так что я очень серьезен, когда говорю миллионы.

Итак, пара вопросов по оптимизации:

  1. Допустим, у меня есть категория «признакам» в пользовательском типе поста, который имеет 500 000 постов. Показанная категория имеет только 500 сообщений. Если я создаю запрос для избранных постов, я запрашиваю все 500 000 постов или только 500 избранных? Что, если я хочу отобразить только десять последних опубликованных сообщений?
  2. При сохранении этого пользовательского типа записи в базе данных, есть ли что-то, что я могу сделать, чтобы сократить ресурсы сервера, тем более что единственное, что действительно нужно, - это содержание сообщения и дата?
  3. Должен ли я даже использовать пользовательский тип сообщения? Мне это нравится в принципе, потому что он хорошо интегрирован в админку WordPress, но если есть существенные недостатки в производительности, то я думаю, что могу сделать что-то другое.

Я никогда не работал над проектом такого масштаба, поэтому я немного больше обеспокоен производительностью, чем обычно. Спасибо за любую помощь!

Иеремия Пруммер
источник
Важно минимизировать количество запросов к базе данных в функциях WordPress и вызывать сценарии соответствующим образом, но большая часть оптимизации связана с настройкой и настройкой сервера. Для этого выполните поиск в сети сбоя сервера. serverfault.com/search?q=optimize+wordpress
iyrin
@RyanLoremIpsum - спасибо за комментарий, но я надеялся получить ответы на мои конкретные вопросы. Большая часть того, что я нашел там, имеет дело с самим сервером, а не с тем, как работает WordPress и как его оптимизировать с точки зрения кода
Джеремия Прумер

Ответы:

26

1. Установите запрос перед запуском WP_Query.

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

Обычные запросы
Для нормального запроса WordPress использует wp()функцию, которая в свою очередь вызывает $wp->main( $query_vars ). «Переменные is_» из условных тегов устанавливаются перед их передачей WP_Query->get_posts(), что преобразует их в запрос к базе данных MySQL и, наконец, сохраняет их в объекте $ wp_query. Можно отфильтровать запрос до его фактического запуска в базе данных SQL .

pre_get_postsДействие перехватывает в этот процесс, что позволяет изменить запрос , прежде чем он передается WP_Query->get_posts().

Например, если вы хотите отфильтровать запрос для сообщений в категории «Избранные», вы должны использовать add_action( 'pre_get_posts', 'your_function_name' );и включать in_categoryусловный тег в your_function_name.

function your_function_name( $query ) {
    if ( $query->in_category( 'featured' ) && $query->is_main_query() ) {
        // Replace 123 with the category ID of the featured category.
        $query->set( 'cat', '123' );
    }
}
add_action( 'pre_get_posts', 'your_function_name' );

См. Плагин API / Справочник по действию / Предварительное получение сообщений «WordPress Codex

Запросы
страницы Что касается шаблонов страниц, таких как страница архива для категории «избранные», условные теги не будут работать из pre_get_postsфильтра. Например, вы не можете использовать is_categoryдля проверки страницы архива, потому что WP_Query не запущен.

Вместо этого вам придется изменить основной запрос для запросов на страницы, new WP_Queryкоторый будет выглядеть примерно так $query = new WP_Query( 'cat=123' );. Это запускает запрос с соответствующим аргументом, установленным с самого начала.

См. Class Reference / WP Query «WordPress Codex

2. Сохранение в базу данных

Вы можете использовать фильтр, wp_insert_post_dataобеспечивающий возврат только тех данных $, которые относятся к вашему типу записи wp_insert_post. Не забудьте включить условный оператор, чтобы проверить свой тип сообщения.
Плагин API / Ссылка на фильтр / wp вставить данные поста «WordPress Codex

Этот хук вызывается wp_insert_postфункцией, которая вызывается wp_update_post, когда вы обновляете свой пользовательский тип сообщения, обычно путем сохранения черновика или публикации сообщения.

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

3. Влияют ли пользовательские типы сообщений на производительность?

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

Раньше существовала проблема производительности, связанная со структурой постоянных ссылок, которая заставляла ее попадать, когда она начинается с текста, а не с числа. 3 Это было особенно проблематично для сайтов, на которых размещено большое количество страниц, но было решено с версии WordPress 3.3.

Я только поднимаю здесь постоянные ссылки, потому что слаг обычно является первой частью структуры постоянных ссылок, которая может повлиять или не повлиять на производительность до версии 3.3. Кроме того, я не знаю каких-либо проблем с производительностью, которые возникают из-за использования пользовательских типов записей.

Другие параметры производительности

Переходные процессы
Это не замена для минимизации количества запросов в вашем коде, но вы можете использовать set_transient для хранения запросов в течение некоторого времени, так что новые запросы не нужны. Вот пример, использованный в посте Дэйва Клемента . Также обратите внимание, что он рекомендует добавить save_postдействие для удаления переходного процесса при каждом обновлении данного типа записи.

<?php // IN THE SPOTLIGHT QUERY
if( false === ( $its_query = get_transient( 'its_query' ) ) ) {
    $pttimestamp = time() + get_option('gmt_offset') * 60*60;
    $its_query = new WP_Query( array(
        'post_type' => 'spotlight',
        'posts_per_page' => 1,
            'post__not_in' => $do_not_duplicate,
        'meta_query' => array(
            array(
                'key' => '_hpc_spotlight_end_time',
                'value' => $pttimestamp,
                'compare' => '>'
            )
        )
    ) );
    set_transient( 'its_query', $its_query, 60*60*4 );
}
if( have_posts() ) { // HIDE SECTION IF NO CURRENT ITS FEATURE ?>
    // LOOP GOES HERE: NOT IMPORTANT TO EXAMPLE
<?php } ?>

Дополнительная оптимизация запросов
Томас Гриффин имеет несколько хороших советов в своем учебнике по оптимизации запросов WordPress . Вот краткий список его предложений:

  • Установите 'cache_results' => falseв одноразовых запросах, если ваш сервер не использует постоянное кэширование, такое как Memcached. Разовые запросы описываются как «запросы, которые используются для отображения небольших объемов данных. Возможно, вы просто хотите отобразить заголовки связанных сообщений, относящиеся к текущему сообщению, или вы можете отобразить раскрывающийся список сообщений, которые можно выбрать для конкретный параметр настройки. "

    Его пример: $query = get_posts( array( 'posts_per_page' => 1, 'cache_results' => false ) );

  • Установите, 'no_found_rows' => trueгде нумерация страниц не требуется. Это «обойдёт MySQL, подсчитывая результаты, чтобы увидеть, нужно ли разбивать на страницы или нет».

    Его пример: $query = new WP_Query( array( 'posts_per_page' => 1, 'no_found_rows' => true ) );

  • Запрос для почтовых идентификаторов только если это все , что вам нужно 'fields' => 'ids' в get_posts. Это должно значительно сократить объем возвращаемых данных, что довольно много для каждого поста, если вы посмотрите на описание базы данных «WordPress Codex

    Его пример: $query = get_posts( array( 'posts_per_page' => 1, 'fields' => 'ids' ) );

В дополнение к этому последнему совету, те же рассуждения могут быть применены, когда вам нужно только одно или несколько полей сообщений с помощью get_post_field .

Наличие четкого понимания того, как работает запрос, очень важно. Чем конкретнее вы можете быть с вашими запросами, тем меньше работы вы будете требовать от базы данных SQL. Это означает, что существует множество возможностей для управления запросами к базе данных. Будьте осторожны с пользовательскими запросами в отношении того, где они выполняются (это страница администратора?), Используйте правильную очистку в прямых запросах и старайтесь использовать встроенные функции WordPress, где это позволяет достичь той же производительности.

iyrin
источник
2
Отличный и очень полезный ответ, спасибо!
Иеремия Пруммер
Тема полностью сделана на заказ, поэтому мы буквально запрашиваем абсолютно необходимые элементы. Это очень полезно, хотя. Учитывая это, я собираюсь вернуться и внести некоторые изменения в мои запросы. ;)
Иеремия Пруммер
1
Я хотел бы добавить, что вы должны избегать мета-запросов, где это возможно. Конечно, не выполняйте запрос к двум метаполям одновременно. Это приводит к двойным и тройным запросам, которые быстро превращаются в проблему производительности. Пользовательские типы сообщений часто могут помочь с этим.
Чарльз Хаймет
3

Я также добавляю:

    'no_found_rows'          => true,
    'update_post_term_cache' => false,
    'update_post_meta_cache' => false,
    'cache_results'          => false
  • no_found_rows (boolean) - делайте это, когда вам не нужно разбивать на страницы и не нужно считать общее количество найденных постов.
  • cache_results (логическое) - кеш информации поста.
  • update_post_meta_cache (boolean) - Опубликовать кэш метаинформации.
  • update_post_term_cache (boolean) - Кэш с информацией о терминах.

Используя эти параметры и передавая значения как FALSE, мы можем ускорить выполнение запроса, прекратив выполнение некоторых дополнительных запросов к базе данных.

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

Пожалуйста, посетите: https://drujoopress.wordpress.com/2013/06/27/how-to-optimize-wordpress-query-to-get-results-faster/#more-184

rigosan
источник
1
Пожалуйста, измените свой ответ и добавьте объяснение: почему это может решить проблему?
Fuxia
Я не могу добавить свой комментарий к этому ответу: wordpress.stackexchange.com/a/166699/57674
rigosan
1

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

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

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

Марк Каплун
источник