2010-10-11 206 views
2

我已经尽了一切努力使这个查询更快,我知道。每个表的引擎相同,所有用于连接的字段的索引,order by或where子句。缓慢的MySQL查询

问题似乎是表aamag没有使用索引,尽管有索引可用。

查询:

SELECT DISTINCT `a`.`id`, `a`.`full_name`, `a`.`rating`, `a`.`licence`, `a`.`licence_issued`, `ag`.`name` as agency_name 
FROM (`property_suburb_map` psm) 
JOIN `campaign_property_map` cpm ON `psm`.`property_id` = `cpm`.`property_id` 
JOIN `campaign` c ON `cpm`.`campaign_id` = `c`.`id` 
JOIN `campaign_agent_map` cam ON `cpm`.`campaign_id` = `cam`.`campaign_id` 
JOIN `agent` a ON `cam`.`agent_id` = `a`.`id` 
JOIN `agency_agent_map` aam ON `aam`.`agent_id` = `a`.`id` 
JOIN `agency` ag ON `aam`.`agency_id` = `ag`.`id` 
WHERE `c`.`closing_date` >= '2009-10-12' 
AND `psm`.`suburb_id` = '5911' 
AND `a`.`status` = 'Active' 
ORDER BY `a`.`rating` DESC, `a`.`full_name` 
LIMIT 12 

解释(对不起,格式化弄乱):使用此图像,而不是http://imgur.com/UzSpC.jpg

id select_type  table   type possible_keys key  key_len  ref  rows Extra 

1 SIMPLE   a    ref  PRIMARY,status status 1 const 790  Using where; Using temporary; Using filesort 
1 SIMPLE   aam    ref  agency_id_2, 
              agent_id, 
              agency_id  agent_id  4  hindsight.a.id 1  
1 SIMPLE   ag    eq_ref PRIMARY  PRIMARY  4 hindsight.aam.agency_id  1  
1 SIMPLE   cam    ref  agent_id, 
              campaign_id  agent_id 4 hindsight.a.id 9 Distinct 
1 SIMPLE   c    eq_ref PRIMARY,closing_date PRIMARY  4 hindsight.cam.campaign_id 1 Using where; Distinct 
1 SIMPLE   cpm    ref  campaign_id  campaign_id  4 hindsight.c.id 1 Using where; Using index; Distinct 
1 SIMPLE   psm    ref  property_id,suburb_id property_id  4 hindsight.cpm.property_id 1 Using where; Distinct 

这里是数据库的相关结构http://pastebin.com/Rbyrj6x3

编辑我在查询中完成了配置文件:Copying to tmp table确实很慢。

mysql> show profile for query 6; 
+----------------------+----------+ 
| Status    | Duration | 
+----------------------+----------+ 
| starting    | 0.000000 | 
| Opening tables  | 0.000000 | 
| System lock   | 0.000000 | 
| Table lock   | 0.000000 | 
| init     | 0.000000 | 
| optimizing   | 0.000000 | 
| statistics   | 0.000000 | 
| preparing   | 0.000000 | 
| Creating tmp table | 0.000000 | 
| executing   | 0.000000 | 
| Copying to tmp table | 0.112000 | <- WTF! 
| Sorting result  | 0.004000 | 
| Sending data   | 0.000000 | 
| end     | 0.000000 | 
| removing tmp table | 0.000000 | 
| end     | 0.000000 | 
| query end   | 0.000000 | 
| freeing items  | 0.000000 | 
| logging slow query | 0.000000 | 
| cleaning up   | 0.000000 | 
+----------------------+----------+ 
20 rows in set (0.00 sec) 
+1

解释显示正在使用aam和ag的索引。我不明白你为什么认为他们没有被使用。 – Martin 2010-10-11 06:33:10

+0

我不是读书专家解释,但会假设'使用索引'会出现在右边(额外)。谢谢你纠正我。如果所有的指标都在使用,我不确定瓶颈在哪里。去除where和order子句对性能没有显着影响,但它仍然需要1秒以上。 – Keyo 2010-10-11 06:43:28

+0

解释输出中的'key'列显示选择了哪个键。如果它包含NULL,则不使用索引。 “使用索引”表示正在使用某种索引扫描(而不是索引查找)。 – Martin 2010-10-11 08:15:41

回答

1

你是否在所有表的所有字段都有外键? 请描述你的表

+0

不,这会有帮助吗?查看上面的pastebin链接以获取表的转储。也许这就是InnoDB需要知道使用哪个索引? – Keyo 2010-10-11 05:41:24

+0

你可以重命名表中的字段吗?仅用于自然连接和简化查询。然后为所有链接的字段添加外键 – 2010-10-11 05:50:08

1

尝试通过增加AGENT_ID作为第二部件转动指数agent.status成覆盖索引:

create index idx2 on agent(status, id) 

这可能使查询面前,消除更多的代理行从数据表中检索记录。

+0

这可以提高性能,可能有10%,但不是很大。也许我的数据库服务器速度很慢。在我的本地主机开发服务器上,它运行时间大约为0.12秒。在生产服务器上大约需要1.8秒。这是这种查询类型的正常速度吗? – Keyo 2010-10-11 23:03:39

+0

很奇怪你的生产服务器比较慢:是因为它上面有更多的数据? – Martin 2010-10-12 03:56:01

+0

对于解释输出,0.12秒似乎确定。主要的问题是,在解决其他任何问题之前,它会从代理表中拉出很多行 - 因此缓慢的临时表。奇怪的是你的生产服务器比较慢:是因为它有更多的数据?你能添加来自“显示变量”的输出吗? – Martin 2010-10-12 04:04:36