2012-12-16 57 views
5

我有一個示例查詢,如:什麼類型的索引是理想的這個查詢?

SELECT 
    rest.name, rest.shortname 
FROM 
    restaurant AS rest 
    INNER JOIN specials ON rest.id=specials.restaurantid 
WHERE 
    specials.dateend >= CURDATE() 
AND 
    rest.state='VIC' 
AND 
    rest.status = 1 
AND 
    specials.status = 1 
ORDER BY 
    rest.name ASC; 

只是想知道以下兩個指標,這將是最好的餐桌?

id,state,status,name 
state,status,name 

只是不確定在連接中使用的列是否應該包含在內?

雖然有趣,但我已經創建了兩種類型的測試,並且兩次MySQL選擇主要索引,這只是id。這是爲什麼?

explain輸出:

1,'SIMPLE','specials','index','NewIndex1\,NewIndex2\,NewIndex3\,NewIndex4','NewIndex4','11',\N,82,'Using where; Using index; Using temporary; Using filesort', 
1,'SIMPLE','rest','eq_ref','PRIMARY\,search\,status\,state\,NewIndex1\,NewIndex2\,id-suburb\,NewIndex3\,id-status-name','PRIMARY','4','db_name.specials.restaurantid',1,'Using where' 

目前不許多行或許這就是爲什麼它的選擇PRIMARY!?

+0

您可以隨時使用'EXPLAIN '獲取有關如何執行選擇查詢的信息。 http://dev.mysql.com/doc/refman/5.0/en/using-explain.html – Cyclonecode

+0

我做過了,這就是我發現它使用'PRIMARY'索引,它只包含'id'列。 – Brett

+0

您是否可以發佈完整的說明輸出和MySQL版本? –

回答

2

爲了獲得最佳性能,你需要至少2個指標:

最重要的指標是一個外鍵:

CREATE INDEX specials_rest_fk ON specials(restaurantid); 

做不到這一點,你的查詢會表現不佳,因爲每一行在rest中,匹配WHERE條件將需要完整的掃描表specials

定義的下一個索引應該是幫助查找給定條件的最少行rest的索引。只有一個索引被使用過,所以你想盡可能地從rest找到這個索引。

我的猜測,和狀態:

CREATE INDEX rest_index_1 on rest(state, status); 

的您的索引的建議(ID,...)是沒有意義的,因爲ID是唯一的 - 增加更多的列將沒有幫助,而且事實上會惡化如果使用它的性能,因爲索引條目會更大,並且每讀取一次I/O頁面時會得到更少的條目。

但是,您可以通過更好地編寫查詢來獲得性能;如果將特殊條件移動到加入ON條件中,您將獲得顯着的性能,因爲連接條件在進行連接時評估,但在所有連接的行上評估條件時,這意味着經過篩選的臨時結果集WHERE條款要大得多,因此要慢一些。

查詢改成這樣:

SELECT rest.name, rest.shortname 
FROM restaurant AS rest 
INNER JOIN specials 
    ON rest.id=specials.restaurantid 
    AND specials.dateend >= CURDATE() 
    AND specials.status = 1 
WHERE rest.state='VIC' 
AND rest.status = 1 
ORDER BY rest.name; 

注意在特價的條件,現在怎麼都ON子句。

+0

是的,我已經在specials表上的'restaurantid'上創建了一個索引。 – Brett

+0

查看編輯答案 – Bohemian

+0

非常感謝!不知道你可以用JOIN做到這一點。幾個問題雖然 - 你在「休息」上創建的索引;由於基數太低,是不是沒有增加「地位」? ...或者不會將'name'添加到最終幫助中,以及看到它在'ORDER BY'中? – Brett

相關問題