在WordPress插件中优化慢速查询"更好的WordPress最新评论"

时间:2015-10-02 20:32:28

标签: mysql wordpress performance select optimization

我正在针对MySQL优化查询,而我的慢查询日志向我显示了WordPress插件"更好的WordPress最新评论"显示按帖子分组的最近5条最近评论的小组件使用1.26秒来查询数据库,这对于网站来说是很长的时间 - 特别是当下一个网站只需点击一下时。

以下是慢查询:

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条评论。这肯定应该可以改进,以便在很短的时间内实际检查一些评论,因为它只显示了最近发表的几条评论。感谢。

2 个答案:

答案 0 :(得分: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 :(得分: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的评论帖ID值,并将其限制为仅6条记录。通过这样做,并加入到那些合格的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 )