Медленная работа сортировки по произвольному полю

Здравствуйте

Столкнулся с такой проблемой - организовываю сортировку постов по произвольному полю (кол-во просмотров):

global $query_string;
query_posts( $query_string . "&meta_key=_post_views_count&orderby=meta_value_num&posts_per_page=64");

Работает, но время генерации страницы увеличивается в 2-3 раза по сравнению с дефолтной выдачей.

Помогите решить

Заметки к вопросу:
samsebesufiy 9.9 лет назад

страница генерируется за 0,18-0,2 сек при тех же 64 постах без сортировки и 0,5 - 0,6 с ней.
меряю функцией

function usage() {
printf(('%d / %s'), get_num_queries(), timer_stop(0, 3));
if ( function_exists('memory_get_usage') ) echo ' / '
 . round(memory_get_usage()/1024/1024, 2) . 'mb '; 
}
add_action('admin_footer_text', 'usage');

соответственно, подгрузка картинок не учитывается

0
Гость
9.9 лет назад
  • 1
    Kama 9824

    Сколько записей на сайте, конкретно этого типа?

    Установите плагин query monitor, найдите этот запрос там, выложите сюда сам SQL запрос. Тогда возможно что-то станет ясно, где там можно улучшить запрос.

    Вообще, сортировка по метаполю в таком случает очень медленная и увеличение количества постов будет значительнее обычного сказываться на скорости. Это потому что при &orderby=meta_value_num SQL переводит каждое значение в числовое и только потом сортирует...

    Если у вас в самом запросе нет чего-то неправильного, то решение тут одно: добавить дополнительное числовое поле в таблицу wp_posts (например views) и сортировать по нему, но это все не так просто.

    samsebesufiy 9.9 лет назад

    постов 2,5к.
    плагин указывает на медленный запрос

    SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
    FROM wp_posts
    INNER JOIN wp_term_relationships
    ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_postmeta
    ON (wp_posts.ID = wp_postmeta.post_id)
    WHERE 1=1
    AND ( wp_term_relationships.term_taxonomy_id IN (2,4,5,6,7,19,20,21,31,35,36,38,49,51,52,53,65,88,95,118,152) )
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish'
    OR wp_posts.post_status = 'private')
    AND (wp_postmeta.meta_key = '_post_views_count' )
    GROUP BY wp_posts.ID
    ORDER BY wp_postmeta.meta_value+0 DESC
    LIMIT 0, 64

    собственно, в нем и дело

    Kama 9.9 лет назад

    Выполнил такой же запрос, на своем сайте, запрос на удивление быстрый...

    У вас что-то с БД походу. Сколько времени на сам запрос уходит? У меня вот что получилось (Обрабатывались тут 1к постов) в 2 раза меньше вашего:

    SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts 
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) 
    INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) 
    WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (2,4,5,6,7,19,20,21,31,35,36,38,49,51,52,53,65,88,95,118,152) ) 
    AND wp_posts.post_type = 'post' 
    AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') 
    AND (wp_postmeta.meta_key = 'views' ) 
    GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 65

    Отображение строк 0 - 64 (65 всего, Запрос занял 0.0073 сек.)

    Сколько времени на запрос у вас уходит?

    Возможно у вас таблицы не оптимизированы, индексы путаются. Их нужно оптимизировать иногда. Поставьте плагин WP Database Optimizer. Запустите оптимизацию и затем проверьте еще раз этот запрос...

    samsebesufiy 9.9 лет назад

    запрос выполняется за 0,24 (!)
    без сортировки - все запросы страницы за < 0,03

    поставил плагин/оптимизировал - запрос выполнился за 0.003!

    Проблема решилась на этом проекте.

    Попробовал такую же штуку провернуть на сайте с 11к постами - чуть быстрее, но 0,3+. Без сортировки, как в предыдущем случае - все запросы страницы за < 0,03

    Эта проблема упоминается здесь и быстрого решения без курения манов, похоже, нет.

    Возможно, подойдет плагин WP Sphinx Search, буду ковырять.

    Спасибо за помощь!

    samsebesufiy 9.9 лет назад

    Гугл солидарен с вами и рекомендует добавить доп. поле в таблицу wp_posts. Расскажите, пожалуйста, как это реализовать

    Kama 9.9 лет назад

    Подробно рассказывать долго и время нет. Коротко так:

    1. Запустите такой запрос в sql:

      ALTER TABLE `wp_posts` ADD `views` BIGINT(20) NOT NULL DEFAULT '0';

      Возможно нужно еще добавить индекс этого поля:

      ALTER TABLE `wp_posts` ADD INDEX `views` (`views`);
    2. Далее, в запрос добавьте сортировку по views

      query_posts( $query_string . "&orderby=views&order=DESC&posts_per_page=64");
    3. Далее, (самое сложное):
      Вам нужно изменить код плагина, который подсчитывает просмотры и сделать так чтобы он записывал их в созданное поле а не в метаполя.
    samsebesufiy 9.9 лет назад

    Этого более чем достаточно. Спасибо!

    Комментировать
На вопросы могут отвечать только зарегистрированные пользователи. Вход . Регистрация