低效的 SQL

发布于 2024-11-05 11:01:21 字数 911 浏览 0 评论 0原文

我不是 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 个。

我想我发现它效率很低,因为它必须每次都计算浏览量/天几千个帖子,但我不知道如何做得更好。

提前致谢。

I'm no MySQL expert, but I've managed until now to hack together something that works. Unfortunately, my latest bodged attempt results in the server dying, so obviously I'm doing something that is massively inefficient. Can anyone give me a hint as to where the problem is and how I might get the same results without bringing the whole site down everytime?

$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);

It uses a post views count to calculate views/day for posts published in the last, then orders them by that number, and grabs the top 4.

I think I see that it's inefficient in that it has to calculate that views/day everytime for a few thousand posts, but I don't know how to do it any better.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月寒剑心 2024-11-12 11:01:21

您可以消除每次调用这些日期函数的需要,方法是将它们静态地传递到 PHP 服务器(可能不与数据库同步)的查询中,或者您可以编写一个存储过程并保存这些日期函数的结果到随后将在查询中使用的变量。

You could eliminate the need to call those date functions every time by either passing them statically into the query from your PHP server (which may not be synced with your database) or you can instead write a stored procedure and save the results of those date functions to variables that will then be used in the query.

ぺ禁宫浮华殁 2024-11-12 11:01:21
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. 用显式的inner join替换了丑陋的隐式where join,这不会做任何事情,只是让事情变得更清晰。它显示的一件事是,如果 wp_postmeta.post_id 是唯一的,那么您不需要分组依据,因为内部联接只会为每个 wp_postmeta 提供一行。 post_id
  3. 添加了一个额外的过滤器来过滤掉浏览量较低的帖子,这限制了 MySQL 必须排序的行数。
  4. 消除了group by只有当wp_postmeta.post_id唯一时这才是正确的!
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;

I've tried to make a few changes.

  1. Replaced the two calls to TO_DAYS with one call to DATEDIFF.
  2. Replaced the ugly implicit where join with an explicit inner join this does not do anything, just makes things clearer. One thing it shows, if wp_postmeta.post_id is unique, then you do not need the group by, because the inner join will only give one row per wp_postmeta.post_id.
  3. Added an extra filter to filter out the posts with a low view count, this limits the amount of rows MySQL has to sort.
  4. Eliminated group by this is only right if wp_postmeta.post_id is unique!
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文