2015-10-02 31 views
4

我正在优化对MySQL的查询和我的慢查询日志显示我的WordPress插件“更好的WordPress最近评论”显示最近5条最新评论的组件帖子,使用1.26秒查询网站很长一段时间的数据库 - 特别是当下一个网站只需点击一下即可。优化WordPress插件中的慢查询“更好的WordPress最近的评论”

这里是慢查询:

Query_time:1.265625 Lock_time:0.000000 Rows_sent:6 Rows_examined:288634

SET时间戳= 1443741678;

SELECT wpcoms.* 
FROM (
SELECT *, 
@num := if(@post_id = comment_post_ID, @num + 1, 1) as row_number, 
@post_id := comment_post_ID as cpID 
FROM wp_comments 
WHERE comment_approved = 1 ORDER BY comment_post_ID DESC, 
comment_ID DESC 
) as wpcoms 
WHERE wpcoms.row_number <= 2 
ORDER BY wpcoms.comment_date DESC 
LIMIT 6; 

行检查说288.634,但我的数据库只包含96.000评论。这当然应该有可能改进,以便在短时间内实际检查几条评论,因为它只显示了最近发布的几条评论。谢谢。

+0

由命令的两个顺序对我来说是可疑的,并确保您的comment_approved和comment_approved字段被索引。你可以做这个没有子选择?你为什么需要row_number?似乎在子查询中唯一的一点是产生row_number – markg

+0

如果是这种情况(https://codex.wordpress.org/Transients_API),将结果放入'transient'缓存中。还要确保查询过程中不存在'sql_calc_found_rows',因为这会在很大程度上影响性能。 – Musk

回答

1

我看到的一个主要问题是内部查询SELECT *, @num...,因为它会导致全表扫描,导致MySQL不使用索引comment_approved

原因很简单,因为如果你看看查询,它实质上是告诉MySQL根据帖子ID排序的表中的每一行,没有限制。

mysql> explain SELECT *, @post_id := comment_post_ID as cpID FROM wp_comments WHERE comment_approved = 1 ORDER BY comment_post_ID DESC, comment_ID DESC LIMIT 10; 
+----+-------------+-------------+------+---------------------------+------+---------+------+------+-----------------------------+ 
| id | select_type | table  | type | possible_keys    | key | key_len | ref | rows | Extra      | 
+----+-------------+-------------+------+---------------------------+------+---------+------+------+-----------------------------+ 
| 1 | SIMPLE  | wp_comments | ALL | comment_approved_date_gmt | NULL | NULL | NULL | 567 | Using where; Using filesort | 
+----+-------------+-------------+------+---------------------------+------+---------+------+------+-----------------------------+ 

问题的另一部分是由comment_post_ID

顺序考虑这个,这将使用索引:

mysql> explain SELECT *, @post_id := comment_post_ID as cpID FROM wp_comments WHERE comment_approved = 1 ORDER BY comment_date_gmt DESC LIMIT 10; 
+----+-------------+-------------+-------+---------------------------+------------------+---------+------+------+-------------+ 
| id | select_type | table  | type | possible_keys    | key    | key_len | ref | rows | Extra  | 
+----+-------------+-------------+-------+---------------------------+------------------+---------+------+------+-------------+ 
| 1 | SIMPLE  | wp_comments | index | comment_approved_date_gmt | comment_date_gmt | 8  | NULL | 10 | Using where | 
+----+-------------+-------------+-------+---------------------------+------------------+---------+------+------+-------------+ 

后者查询可能会影响你的结果,但它会更有效。

更好的解决方案可能是MySQL查询和PHP过滤的某种组合,以获得期望的结果。

由于这是一个插件,您可能会考虑将其作为插件开发人员的一个问题,因为它会导致任何网站有大量评论的糟糕表现。

这个答案绝不是一个解决方案,但希望指出你在正确的方向。查询和处理的逻辑需要真正重新考虑,当涉及到有很多评论的网站时。

+1

我试过了你的建议,只是通过在“ORDER BY comment_post_ID DESC,comment_ID DESC”中包含** LIMIT 100 **,查询从1.265秒改进为0.125秒。 通过将ORDER BY字段更改为“** comment_date_gmt **”以及完全建议的LIMIT 100,将查询改进为0.0000秒。大奖! 非常感谢,drew010!我会通知插件的开发者更改他的代码。我已经使用你的新语句更新了.php文件,并且它非常完美! :-) – Frank

+0

@Frank我很高兴你能够改变查询与我的建议,并获得预期的结果,同时看到巨大的性能提高。乐意效劳! – drew010

1

没有看到实际的数据,并做了一些有点教育的猜测,你正在寻找最新的“批准”的职位,然后想要获得最新的每条帖子2评论。整体查询是好的,我只是更进一步,给它一个镜头。

SELECT 
     wpcoms.* 
    FROM 
     (SELECT 
       *, 
       @num := if(@post_id = c1.comment_post_ID, @num + 1, 1) as row_number, 
       @post_id := c1.comment_post_ID as cpID 
      FROM 
       (select distinct c2.comment_post_id 
        from wp_comments c2 
        where c2.comment_approved = 1 
        order by c2.comment_post_id desc 
        limit 6) Just6 
        JOIN wp_comments c1 
        ON Just6.comment_post_id = c1.comment_post_id 
      WHERE 
       c1.comment_approved = 1 
      ORDER BY 
       c1.comment_post_ID DESC, 
       c1.comment_ID DESC 
    ) as wpcoms 
    WHERE 
     wpcoms.row_number <= 2 
    ORDER BY 
     wpcoms.comment_date DESC 
    LIMIT 6; 

唯一真正的调整是有一个内部子查询预资格是有一个评论被批准DISTINCT PER COMMENT_POST_ID并限制了只有6只记录评论发表的ID值。通过这样做,然后回到关于那些有资格的comment_post_id的评论表,你不会查询每一个可能的帖子,只是排位赛6.从那以后,这些评论减少到每个评论帖子最多只有2个,然后最终确定您的列表可以减少到6个条目。但是,如果你总是需要6条评论帖子,请摆脱外部限制6。这样,您最多可以有12个条目,这对于6个内部限定的评论帖子ID值是2。

现在,不知道你的索引,我会建议您的wp_comments表中的以下两个复合索引。但至少索引#1

1. (comment_approved, comment_post_id) 
2. (comment_post_id, comment_id)