MySQL加入子选择优化

时间:2011-02-08 19:50:30

标签: sql mysql

UPDATE users u
JOIN (select count(*) as job_count, user_id from job_responses where date_created > subdate(now(), 30) group by user_id) j
ON j.user_id = u.user_id
JOIN users_profile p
ON p.user_id = u.user_id
JOIN users_roles_xref x
ON x.user_id = u.user_id
SET num_job_responses = least(j.job_count, 5)
WHERE u.status = 1 AND p.visible = "Y" AND x.role_id = 2000

并解释告诉我:

+----+-------------+---------------+--------+---------------------------------+---------------+---------+----------------------+--------+----------------------------------------------+
| id | select_type | table         | type   | possible_keys                   | key           | key_len | ref                  | rows   | Extra                                        |
+----+-------------+---------------+--------+---------------------------------+---------------+---------+----------------------+--------+----------------------------------------------+
|  1 | PRIMARY     | <derived2>    | ALL    | NULL                            | NULL          | NULL    | NULL                 |  23008 |                                              | 
|  1 | PRIMARY     | u             | eq_ref | PRIMARY,user_id,status,status_2 | PRIMARY       | 4       | j.user_id            |      1 | Using where                                  | 
|  1 | PRIMARY     | p             | ref    | user_id,visible                 | user_id       | 4       | scoop_jazz.u.user_id |      2 | Using where                                  | 
|  1 | PRIMARY     | x             | ref    | index_role_id,index_user_id     | index_user_id | 4       | scoop_jazz.u.user_id |      3 | Using where                                  | 
|  2 | DERIVED     | job_responses | range  | date_created                    | date_created  | 4       | NULL                 | 135417 | Using where; Using temporary; Using filesort | 
+----+-------------+---------------+--------+---------------------------------+---------------+---------+----------------------+--------+----------------------------------------------+

我在使用explain优化此查询时遇到问题。有办法吗?

2 个答案:

答案 0 :(得分:1)

您需要在job_responses(date_created,user_id)上添加索引。 然后,您可以删除date_created上的当前单列索引。

查询中最昂贵的部分是子查询

(select count(*) as job_count, user_id
 from job_responses
 where date_created > subdate(now(), 30)
 group by user_id)

唯一需要注意的两个字段是user_id和date_created。 date_created上有一个索引已被选中以满足date_created in last 30 days。但是,它必须返回到数据页以检索user_id,然后按其分组。

如果您有复合索引,则user_id可直接从索引中获得。它还涵盖了单列索引date_created,因此您可以删除该索引。

答案 1 :(得分:0)

它最终变得更容易,更快速地生成临时表,填充它,然后在该表上使用连接。我正在“分块”原始查询,当它必须创建和销毁由子选择创建的表时,最终会非常昂贵。