#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;
Я попытался внести несколько изменений.
- Заменил два вызова на
TO_DAYS
одним вызовом наDATEDIFF
. - Заменил уродливое неявное соединение where на явное
inner join
это ничего не делает, просто проясняет ситуацию. Это показывает одну вещь, еслиwp_postmeta.post_id
она уникальна, то вам не нужна group by, потому что внутреннее объединение выдаст только одну строку наwp_postmeta.post_id
. - Добавлен дополнительный фильтр для отсеивания сообщений с низким количеством просмотров, это ограничивает количество строк, которые MySQL должен сортировать.
- Устранено,
group by
это правильно, только еслиwp_postmeta.post_id
является уникальным!
Комментарии:
1. спасибо, Йохан — на самом деле у меня возникли проблемы с двумя мета-значениями, создаваемыми для свойства views определенных сообщений, так что это было сделано для решения этой проблемы. Безусловно, было бы лучшей идеей очистить базу данных и сделать это так, как вы предложили. Я никогда не был слишком уверен во внутренних соединениях, поэтому я проведу небольшое исследование по этому вопросу; и дополнительный фильтр — отличная идея. Спасибо!
2. хорошо, я попробовал это, и он вернул те же 4 сообщения. При ближайшем рассмотрении кажется, что в конкретном сообщении было 6 записей для meta_key «views», все с одинаковым номером, но с другим meta_id. странно….
3. вместо этого он выбрал DISTINCT и увеличил фильтр до> 1000 сообщений. Работай, но я все еще чувствую, что делаю здесь что-то в корне неправильное…