2009-08-14 153 views
1

我有以下查詢:如何優化此查詢?

SELECT `masters_tp`.*, `masters_cp`.`cp` as cp, `masters_cp`.`punti` as punti 
FROM (`masters_tp`) 
LEFT JOIN `masters_cp` ON `masters_cp`.`nickname` = `masters_tp`.`nickname` 
WHERE `masters_tp`.`stake` = 'report_A' 
AND `masters_cp`.`stake` = 'report_A' 
ORDER BY `masters_tp`.`tp` DESC, `masters_cp`.`punti` DESC 
LIMIT 400; 

有什麼不對的查詢可能影響服務器的內存?

這裏是輸出EXPLAIN

| id | select_type | table  | type | possible_keys | key | key_len | ref | rows | Extra          | 
+----+-------------+------------+------+---------------+------+---------+------+-------+----------------------------------------------+ 
| 1 | SIMPLE  | masters_cp | ALL | NULL   | NULL | NULL | NULL | 8943 | Using where; Using temporary; Using filesort | 
| 1 | SIMPLE  | masters_tp | ALL | NULL   | NULL | NULL | NULL | 12693 | Using where         | 
+0

我們不可能在沒有更多信息的情況下回答這個問題。也許關於表格的一些信息以及它們中有多少數據? – scheibk 2009-08-14 10:56:54

回答

2

這是簡單的查詢。我認爲一切都很好。您可以嘗試在「股份」字段中添加索引或降低限制。

6

運行與EXPLAIN前綴相同的查詢,並將輸出添加到您的問題 - 這將顯示您正在使用的索引和正在分析的行數。

您可以從您的解釋中看到,沒有索引正在使用,並且必須查看數千行才能獲得結果。嘗試在用於執行連接的列上添加索引,例如暱稱和股份:

ALTER TABLE masters_tp ADD INDEX(nickname),ADD INDEX(stake); 
ALTER TABLE masters_cp ADD INDEX(nickname),ADD INDEX(stake); 

(我假定列有可能重複值,如果沒有,使用唯一的,而不是INDEX)。有關更多信息,請參閱MySQL manual

+0

結果上EXPLAIN ID = 1 SELECT_TYPE = SIMPLE 表= masters_cp 類型= ALL possible_keys = NULL 鍵= NULL key_len = NULL REF =空 行= 8943 額外=使用其中;使用臨時;使用文件排序 ID = 1 SELECT_TYPE = SIMPLE 表= masters_tp 類型= ALL possible_keys = NULL 鍵= NULL key_len = NULL REF = NULL 行數= 12693 額外=使用其中 – insic 2009-08-14 11:07:19

+0

感謝您的幫助,我現在真的很慢,我不能重寫查詢。除此之外,我還需要閱讀如何爲MySQL連接索引 – insic 2009-08-14 11:47:22

5

通過明確命名您實際需要的表中的字段來替換「masters_tp。*」位。即使你需要他們,把他們全部命名。

+0

,謝謝我會這樣做。 – insic 2009-08-14 11:51:17

5

實際上沒有理由在這裏做left join。您正在使用您的過濾器來掃除連接的任何左側。試試這個:

SELECT 
    `masters_tp`.*, 
    `masters_cp`.`cp` as cp, 
    `masters_cp`.`punti` as punti 
FROM 
    `masters_tp` 
    INNER JOIN `masters_cp` ON 
     `masters_tp`.`stake` = `masters_cp`.stake` 
     and `masters_tp`.`nickname` = `masters_cp`.`nickname` 
WHERE 
    `masters_tp`.`stake` = 'report_A' 
ORDER BY 
    `masters_tp`.`tp` DESC, 
    `masters_cp`.`punti` DESC 
LIMIT 400; 

inner join小號往往比left join速度比較快。該查詢可以限制必須使用謂詞連接的行數(也稱爲where子句)。這意味着數據庫可能會處理更少的行,這顯然會加快速度。

此外,請確保您有一個非聚集索引stakenickname(按此順序)。

+0

他實際上可能希望左連接的關鍵是將該條件從何處轉移到連接處。你現在是對的,由於代碼錯誤,它沒有返回一個左連接。 – HLGEM 2009-08-14 19:27:16