如何优化这个复杂的查询?

时间:2014-04-18 20:56:06

标签: mysql sql

我如何优化此查询?现在它在0.0100秒内执行。

SELECT comments.comment_content, comments.comment_votes, comments.comment_date,
  users.user_login, users.user_level, users.user_avatar_source, 
  groups.group_safename 
FROM comments
LEFT JOIN links ON comment_link_id=link_id 
LEFT JOIN users ON comment_user_id=user_id
LEFT JOIN groups ON comment_group_id=link_group_id 
WHERE comment_status='published' AND link_status='published' 
ORDER BY comment_id DESC

EXPLAIN输出:

enter image description here

索引:

注释:

enter image description here

用户:

enter image description here

组:

enter image description here

1 个答案:

答案 0 :(得分:1)

低于二十毫秒的查询时间通常被认为是慢的。正如一些人在评论中提到的那样,当你的表变大时,你需要重做优化,因为MySQL的优化器(以及其他RDMS的优化器)根据索引大小做出决策。

我建议您始终使用表名或别名限定JOIN子句中的列名。例如,您可以使用以下样式获得清晰度和可维护性:

FROM comments AS c
LEFT JOIN links AS L ON c.comment_link_id=L.link_id 
LEFT JOIN users AS u ON c.comment_user_id=u.user_id
LEFT JOIN groups AS g ON c.comment_group_id=g.link_group_id

此查询选择了相当宽的表子集,因此表格越大,运行速度越慢。除非你能以某种方式缩小子集,否则这是不可避免的。

您在JOIN ... ON操作中使用的列是否都已声明为NOT NULL?他们应该是。

查看您使用groups表格的方式:您已加入link_group_id并检索group_safename。因此,在(link_group_id,group_safename)上尝试覆盖索引的复合词。索引至少为link_group_id

users表:您已经在user_id上找到了索引。当您的表格变大时,(user_id, user_login, user_level, user_avatar_source)上的复合覆盖索引可能有所帮助。但这是一个低优先级的尝试。

links表格:您正在使用link_statuslink_id。此表的LEFT JOIN应该是普通内部JOIN,因为其中一列显示在WHERE子句中。如果您的应用程序中link_status可以是NOT NULL,请确保以此方式声明它。然后在(link_status, link_id)上尝试复合索引。

comments表:就我所见,您在comment_status上没有索引。尝试添加一个。

然后在表中放入一堆数据,为每个表运行OPTIMIZE LOCAL TABLE,然后再次使用EXPLAIN尝试查询。