1

我有这个查询需要 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)

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

4

2 回答 2

2

尝试创建索引

ocal_favs ( clipart_id, username )

并确保有NOT NULL约束ocal_favs.username或添加ocal_favs.username IS NOT NULL为条件。

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

于 2012-07-02T11:59:16.537 回答
1

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

于 2012-07-02T11:59:36.317 回答