Оптимизация WordPress запросов к базе данных

Admin MySQL, PHP, WordPress Обсудить

WordPress не заточен под кастомизацию. Нативные функции работают быстро, но если надо вывести посты с определенным набором критериев, то он достаточно медлителен.

Надо было проверить скорость работы в одном из разделов одного сайта и случайно увидел на главной странице медленный запрос:

Один запрос отнимал половину секунды. Из скрина видно, что запрос ужасен. Он содержит в себе много лишнего и дублирующего.

Это был запрос, который изменял функцию query_posts() для вывода постов по определенным критериям. Возможно содержал ошибки и можно было его переписать иначе, но с виду вроде ничего лишнего.

Суть была в том, что есть мета-поле с датой. И по ключу этого мета-поля мы получали последние 4 записи до сегодняшней даты.

<?php
$paged = get_query_var('paged', 1);

$date = date('Y-m-d', strtotime('-10 year'));
$today   = date('Y-m-d');

$args = [
    'post_type' => 'post',
    'meta_key'  => 'premiere_ru',
    'paged'     => $paged,

    'meta_query' => [
        'key'     => 'premiere_ru',
        'value'   => [$date, $today],
        'type'    => 'DATE',
        'compare' => 'BETWEEN'
    ],

    'orderby'        => 'meta_value',
    'order'          => 'DESC',
    'posts_per_page' => '4'
];
query_posts($args);
?>

Этот запрос я переписал напрямую запрашивая данные в БД MySQL:

    /**
     * Получает из БД 4 последних вышедших в кино фильмов
     *
     * @return array
     */

    public static function getLastMovie()
    {
        $today = date('Y-m-d');
        $sql   = "
        SELECT ID
        FROM wp_posts as p
           
        LEFT JOIN wp_postmeta as pm
        ON p.ID = pm.post_id
               
        WHERE p.post_type = 'post'
        AND p.post_status = 'publish'
        AND pm.meta_key = 'premiere_ru'
       
        # CAST - приводим формат к формату даты
        # Ставим по сегодняшнее число, чтобы не забирать фильмы, который только выйдут
        AND CAST(pm.meta_value AS DATE) BETWEEN '2019-01-01' AND %s
       
        ORDER BY pm.meta_value DESC
        LIMIT 0, 4
    "
;

        global $wpdb;
        $data = $wpdb->get_results($wpdb->prepare($sql, $today), ARRAY_A);
        return $data;
    }

После внесения изменений, тяжелый запрос исчез и страница стала грузиться быстрее:

Вместо 0.5 переписанный запрос стал занимать 0,0142 секунды, т.е. в 35 раз быстрее.

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

Но такие изменения не проходят малыми усилиями, приходится переписывать и концепцию вывода постов. Отходить от

if (have_posts()) : while (have_posts()) : the_post(); endif;

И генерировать данные через foreach(), что требует времени на переписывание старого функционала.

Привет. Ты находишься на моём сайте. Я разработчик. Здесь я делюсь своими наработками и знаниями. Спрашивай в комментариях, если тебе что-то не понятно или пиши, если есть что добавить.

Если вам пригодилась информация, вы можете поблагодарить автора сайта символическим пожертвованием:

Добавить комментарий

Напишите свой комментарий, если вам есть что добавить/поправить/спросить по теме текущей статьи: "Оптимизация WordPress запросов к базе данных"
Если вам нужно добавить участок кода ставьте его между тегами <code></code>