2010-10-11 204 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