可以优化此MySQL连接查询吗?

时间:2012-07-02 11:34:05

标签: mysql sql query-optimization

我有这个查询需要27秒才能执行:

SELECT ocal_files.*, count(DISTINCT ocal_favs.username) as favs 
FROM ocal_files
   INNER JOIN ocal_favs on ocal_favs.clipart_id = ocal_files.id 
GROUP BY ocal_files.id 
ORDER BY favs DESC​

(而不是用户名,应该是user_id,因为我有用户表)

ocal_files有37457行,ocal_favs有18263

编辑解释结果

mysql> EXPLAIN SELECT ocal_files.*, count(DISTINCT ocal_favs.username) as favs FROM ocal_files INNER JOIN ocal_favs on ocal_favs.clipart_i
d = ocal_files.id GROUP BY ocal_files.id ORDER BY favs DESC;                                                                             
+----+-------------+------------+--------+----------------+---------+---------+---------------------------------+-------+---------------------------------+
| id | select_type | table      | type   | possible_keys  | key     | key_len | ref                             | rows  | Extra                           |
+----+-------------+------------+--------+----------------+---------+---------+---------------------------------+-------+---------------------------------+
|  1 | SIMPLE      | ocal_favs  | ALL    | rlb_clipart_id | NULL    | NULL    | NULL                             | 18622 | Using temporary; Using filesort|
|  1 | SIMPLE      | ocal_files | eq_ref | PRIMARY        | PRIMARY | 4       | openclipart.ocal_favs.clipart_id |     1 | Using where                    |
+----+-------------+------------+--------+----------------+---------+---------+---------------------------------+-------+---------------------------------+
2 rows in set (0.00 sec)

为什么慢?可以优化吗?如果是,那么如何?

2 个答案:

答案 0 :(得分:2)

尝试在

上创建索引
ocal_favs ( clipart_id, username )

并确保NOT NULL上存在ocal_favs.username约束或添加ocal_favs.username IS NOT NULL作为条件。

这应该允许从ocal_files和该索引获取所有信息。

答案 1 :(得分:1)

处理SQL优化时的一个好方法是选择您需要的字段,而不是所有字段。这几乎总是会对性能产生巨大影响,尤其是当字段为BLOB's时。 并且,正如其他用户所指出的那样 - 索引也非常重要,但前提是你已经正确创建了索引。 使用LIMIT条款也是个好主意,如果你不需要立刻显示你的结果(我怀疑这是这种情况,因为我不相信你会显示用户浏览器的30000条记录的结果)...