使用多个连接优化MySQL Count查询

时间:2013-03-07 17:12:49

标签: mysql sql ruby-on-rails

我有一个SQL查询,需要3.5秒才能返回一个计数。查看查询的跟踪,看起来正在使用所有索引。我该怎么做才能优化它以合理执行?

我提前感谢。


Link to trace

SQL详细信息

查询

SELECT count(DISTINCT `workorders`.id) AS count_all FROM `workorders` 
LEFT OUTER JOIN `users` ON `users`.id = `workorders`.user_id 
LEFT OUTER JOIN `assets` ON `assets`.id = `workorders`.asset_id 
LEFT OUTER JOIN `users` completed_by_users_workorders ON `completed_by_users_workorders`.id = `workorders`.completed_by_user_id 
LEFT OUTER JOIN `messages` ON messages.workorder_id = workorders.id LEFT OUTER JOIN `priorities` ON `priorities`.id = `workorders`.priority_id 
LEFT OUTER JOIN `suspension_reasons` ON `suspension_reasons`.id = `workorders`.suspension_reason_id 
LEFT OUTER JOIN `job_types` ON `job_types`.id = `workorders`.job_type_id 
LEFT OUTER JOIN `workorder_statuses` ON `workorder_statuses`.id = `workorders`.workorder_status_id 
LEFT OUTER JOIN `workorder_types` ON `workorder_types`.id = `workorders`.workorder_type_id 
LEFT OUTER JOIN `workorder_tasks` ON workorder_tasks.workorder_id = workorders.id 
LEFT OUTER JOIN `frequencies` ON `frequencies`.id = `workorder_tasks`.frequency_id 
LEFT OUTER JOIN `facilities` ON `facilities`.id = `workorders`.facility_id 
LEFT OUTER JOIN `locations` ON `locations`.id = `workorders`.location_id 
WHERE ((((workorders.workorder_status_id = ?)) AND (workorders.application = ?)) AND (workorders.facility_id = ?))

时长3,791毫秒 查询分析(显示详细信息)

微量 * 工作订单 *
使用以下索引检索表:facility_id,app_fac,workorder_status_id 您可以通过仅查询索引中的字段来加速此查询。或者,您可以创建包含查询中每个字段的索引,包括主键。

扫描了该表的大约33850行。

用户
使用此索引检索表:PRIMARY 扫描了该表的大约1行。

资产
使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

completed_by_users_workorders
使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

讯息
使用以下索引检索表:workorder_id

扫描了该表的大约2行。

优先级
使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

suspension_reasons
使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

job_types
使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

workorder_statuses
使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

workorder_types 使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

workorder_tasks 使用以下索引检索表:index_workorder_tasks_on_workorder_id 您可以通过仅查询索引中的字段来加速此查询。或者,您可以创建包含查询中每个字段的索引,包括主键。

扫描了该表的大约1行。

频率 使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

设施
使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

地点
使用以下索引检索表:PRIMARY

扫描了该表的大约1行。

1 个答案:

答案 0 :(得分:2)

除非我遗漏了某些东西,否则你有大量的LEFT JOIN s不影响最终结果(你选择的是distinct workorders.id - 我猜这是一个PK列。然后只有重要的地方, WHERE ((((workorders.workorder_status_id = ?)) AND (workorders.application = ?)) AND (workorders.facility_id = ?)。所以我相信你可以摆脱所有的LEFT JOIN并写下来从1表中选择,让优化生活变得更加容易....

SELECT count(*) AS count_all
FROM `workorders`
WHERE ((((workorders.workorder_status_id = ?)) AND (workorders.application = ?)) AND   
(workorders.facility_id = ?)

上面的查询应该会给你与原始查询相同的结果,但工作量会少得多。