2010-11-15 102 views
1

我需要一些幫助優化MySQL查詢或表MySQL的加入時間太長

當我運行此查詢它.01s 650次返回的記錄:

select mm, name, display, year 
    from tbl d 
    where active = 1 and tbl2_id = 'val' and lvl_id = 9 
    order by mm; 

當我運行此查詢它長達15秒返回與相同的記錄:

select d.mm, d.name, d.display, d.year, a.year year2 
    from tbl d left join tbl a on d.mm = a.mm and a.tbl2_id = 'val2' 
    where d.active = 1 and d.tbl2_id = 'val' and d.lvl_id = 9 
    order by d.mm; 

當我運行它,這樣它也需要長達15秒:

select mm, name, display, year, 
     (select a.year from tbl a where a.mm = mm and a.tbl2_id = 'val2') year2 
    from tbl 
    where active = 1 and tbl2_id = 'val' and lvl_id = 9 
    order by mm; 

表中有多個mm記錄。我需要得到tbl2_id ='val'的所有記錄,並且如果有這樣的記錄,那麼tbl2_id ='val2'時,我需要val2記錄中的「年份」值。 tbl目前有13k條記錄,並且沒有超過10條記錄,所以我不認爲這個查詢應該超過15秒。我有索引mm,active,tbl2_id和lvl_id。

我已經做過類似的事情在MSSQL,幾乎沒有延遲。

+2

你可以在你的查詢上運行'EXPLAIN'併發布查詢計劃嗎? http://dev.mysql.com/doc/refman/5.0/en/explain.html – thomaspaulb 2010-11-15 22:23:45

回答

3

您可以通過在(tbl2_id,lvl_id,有源)和(tbl2_id,毫米)你的桌子上引入複合索引開始。這可能會加快你的三個疑問。

每當在WHERE子句中使用多個字段,這是有道理考慮一個綜合指數。在情況下,只有單個列索引存在,查詢可以僅使用這些索引中的一個爲一個而不必訴諸較慢掃描搜索剩餘的子集尋求。 MySQL和MSSQL在這方面的區別可能在於,MSSQL根據數據的基數(最好使用的是離開掃描的最小子集的數據)來更好地猜測這三者中哪一個可以使用,儘管如果沒有詳細檢查兩個查詢計劃,這很難說。

+0

對不起,它應該是a.mm = mm。我會解決它。 – 2010-11-15 22:34:27

+0

好的,在這種情況下,索引建議對所有三個查詢都有效。答案已更新。 – thomaspaulb 2010-11-15 22:40:45

+0

快速的網頁搜索「複合索引mysql」後,我能夠創建一個新的索引(mm,tbl2_id,lvl_id,動作),這有助於顯着。現在,連接與我的第一個查詢運行大致相同。 – 2010-11-15 22:49:58

1

索引連接條件(mm)中使用的列應該有所幫助。

+0

這個問題表明這樣一個索引已經存在。 – 2010-11-15 22:26:18

2

你能提供的表的DESCRIBE和查詢的EXPLAIN

使用字符串查找INT字段或整數以查找CHAR/VARCHAR字段存在已知問題。基本上INDEX被忽略。

如果lvl_idactiveCHAR/VARCHAR這可能是原因。如果這種類型爲INT,則tbl2_id也是如此。

編輯

我必須說,13K條目是沒有什麼可以解釋的性能。但是,您應該考慮索引的基數。如果基數低於30%(等因素),您的指數將不會被使用。

使用EXPLAIN當問如何查詢優化器做了查詢,並利用它什麼索引這應該是清楚的。在某些情況下,您可能希望使用FORCE INDEX語法明確使用一個或多個索引。

另外請記住,雖然添加複合索引有助於提高查詢速度(通過增加索引的基數並因此使查詢優化器自動使用它),但它也會有不利之處。更多索引意味着更多的空間使用和減速UPDATE/INSERT因爲更多的東西需要更新。如果表格變得相當大(在數百萬行的範圍內),這尤其相關。