Неэффективный SQL

#mysql #sql #wordpress

#mysql #sql #wordpress

Вопрос:

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

 $sqlbest = "SELECT  
        wp_postmeta.meta_value 
      , wp_posts.post_title 
      , wp_posts.ID
      , (TO_DAYS(CURDATE())- TO_DAYS(wp_posts.post_date)) 1 AS days 
    FROM  `wp_postmeta` ,  `wp_posts` 
WHERE  `wp_postmeta`.`post_id` =  `wp_posts`.`ID` 
  AND  `wp_posts`.`post_date` >= DATE_SUB( CURDATE( ) , INTERVAL 1 WEEK) 
  AND  `wp_postmeta`.`meta_key` =  'views' 
  AND  `wp_posts`.`post_status` =  'publish' 
  AND wp_posts.ID != '".$currentPostID."'
GROUP BY  `wp_postmeta`.`post_id` 
ORDER BY (CAST(  `wp_postmeta`.`meta_value` AS UNSIGNED ) / days) DESC 
LIMIT 0 , 4";

$results = $wpdb->get_results($sqlbest);
  

Он использует количество просмотров сообщений для вычисления просмотров в день для сообщений, опубликованных в последнем, затем упорядочивает их по этому числу и захватывает верхние 4.

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

Заранее спасибо.

Комментарии:

1. Вы уверены, что это проблема эффективности, а не простая синтаксическая ошибка или что-то еще в коде, вызывающее ошибку? Что именно происходит, вы получаете какие-либо ошибки?

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

3. попробуйте исключить предложение ‘order by’, посмотрите, поможет ли это

4. это работает, поэтому не может быть синтаксисом. но когда запрос выполняется одновременно многими пользователями, система рушится. запускайте напрямую через phpmyadmin, он тоже работает, со временем выполнения 0,36 секунды. Что касается предложения order-by — как еще я мог бы получить 4 лучших результата? В этом-то и весь смысл…

5. И, пожалуйста, прекратите использовать подразумеваемый синтаксис, он устарел на 19 лет!

Ответ №1:

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

Комментарии:

1. Думаю, я вас понял. Но используют ли функции даты MySQL столько ресурсов?

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

Ответ №2:

 SELECT  
  wp_postmeta.meta_value 
  , wp_posts.post_title 
  , wp_posts.ID
  , DATEDIFF(CURDATE(),wp_posts.post_date) 1 AS days <<--1: DATEDIFF
FROM  wp_postmeta
INNER JOIN wp_posts ON (wp_postmeta.post_id =  wp_posts.ID) <<--2: explicit join
WHERE wp_posts.post_date >= DATE_SUB( CURDATE( ) , INTERVAL 1 WEEK) 
  AND wp_postmeta.meta_key = 'views' 
  AND wp_posts.post_status = 'publish' 
  AND wp_posts.ID != '".$currentPostID."'
  AND wp_postmeta.meta_value > 1   <<-- 3: extra filter
/*GROUP BY wp_postmeta.post_id */  <<-- 4: group by not needed
ORDER BY (CAST( wp_postmeta.meta_value AS UNSIGNED ) / days) DESC 
LIMIT 0 , 4;
  

Я попытался внести несколько изменений.

  1. Заменил два вызова на TO_DAYS одним вызовом на DATEDIFF .
  2. Заменил уродливое неявное соединение where на явное inner join это ничего не делает, просто проясняет ситуацию. Это показывает одну вещь, если wp_postmeta.post_id она уникальна, то вам не нужна group by, потому что внутреннее объединение выдаст только одну строку на wp_postmeta.post_id .
  3. Добавлен дополнительный фильтр для отсеивания сообщений с низким количеством просмотров, это ограничивает количество строк, которые MySQL должен сортировать.
  4. Устранено, group by это правильно, только если wp_postmeta.post_id является уникальным!

Комментарии:

1. спасибо, Йохан — на самом деле у меня возникли проблемы с двумя мета-значениями, создаваемыми для свойства views определенных сообщений, так что это было сделано для решения этой проблемы. Безусловно, было бы лучшей идеей очистить базу данных и сделать это так, как вы предложили. Я никогда не был слишком уверен во внутренних соединениях, поэтому я проведу небольшое исследование по этому вопросу; и дополнительный фильтр — отличная идея. Спасибо!

2. хорошо, я попробовал это, и он вернул те же 4 сообщения. При ближайшем рассмотрении кажется, что в конкретном сообщении было 6 записей для meta_key «views», все с одинаковым номером, но с другим meta_id. странно….

3. вместо этого он выбрал DISTINCT и увеличил фильтр до> 1000 сообщений. Работай, но я все еще чувствую, что делаю здесь что-то в корне неправильное…