2012-02-10 45 views
2

我的工作,在約1.2秒運行在由126000點的記錄填充的MyISAM表的簡單查詢:MySQL的簡單,但慢查詢(錯誤索引?)

SELECT * FROM my_table 
WHERE primary_key != 5 AND 
(
    col1 = 528 OR (col2 = 265 AND col3 = 1) 
) 
ORDER BY primary_key DESC 

我已經爲建立單一指標where子句中使用的每個字段,但只有primary_key(my_table的自動增量字段)用作關鍵字,而col1和col2僅被忽略,查詢變得更慢。我應該如何創建索引(可能是多索引)或編輯查詢?

+0

索引必須與查詢(DESC)保持同一方向。 – Alfabravo 2012-02-10 17:10:41

回答

0

使用EXPLAIN找出發生了什麼。這將標識正在使用哪些索引,從而使您能夠調整查詢。

0

不幸的是,幾乎沒有辦法預測哪些索引在沒有對MySQL內部的全面理解的情況下會比其他索引更好。但是,對於每個查詢(或者至少子查詢/連接),MySQL只會使用1個索引,因此您已經聲明主鍵正在使用,所以我假設您已經查看了EXPLAIN輸出。

您可能希望嘗試使用不同順序在(primary_key,col1,col2,col3)或其中的一個子集上的多列索引來查找最佳結果。最好的索引將主要取決於列的基數,因此甚至可能隨時間而改變,這取決於表中的數據。

4

,如果你有以下的多列「覆蓋」指標,您將獲得最佳性能:

(primary_key, col1) 
(primary_key, col2, col3) 

,併發出以下查詢:

(SELECT * FROM my_table 
WHERE primary_key != 5 AND 
    col1 = 528) 
UNION 
(SELECT * FROM my_table 
WHERE primary_key != 5 AND 
col2 = 265 AND col3 = 1) 
ORDER BY primary_key DESC 

你可能會變化,更好,性能通過改變索引中字段的順序,基於基數。

在您原來的查詢中,WHERE子句中的整個選擇都不會使用索引,這會導致部分表掃描。

在上面的查詢中,第一個子查詢能夠完全利用第一個索引,避免任何表掃描,第二個子查詢使用第二個索引。

不幸的是,MySQL將無法利用索引對整個結果集上的記錄進行排序,並可能使用filesort對它們進行排序。因此,如果您不需要按primary_key排序的記錄,請刪除外部的ORDER子句以獲得更好的性能,但如果結果集較小,則不應該成爲問題。