2012-04-15 63 views
1

我有50萬行,看起來像這樣的表:http://d.pr/njFJ提高MySQL查詢的任何提示?

enter image description here

這樣的查詢有時往往需要超過2秒:

SELECT * 
FROM `alerts` 
WHERE `a_timestamp` > '2012-04-15' AND `a_timestamp` <= '2012-04-16' 
    AND a_company_id IN(64,65,69,70,71,72,73,74,75,76,83,86,106,108,109,116,148) ORDER BY a_id DESC 

這裏的解釋查詢:http://d.pr/z20b

enter image description here

有人可以指出我做錯了什麼嗎?也許我錯過了一些東西。它應該在這樣一張小桌子上花費那麼多時間嗎?

+0

圖片壞對不起 – Joel 2012-04-15 18:20:52

+0

@ Joel :)他們在哪裏?圖像清晰。 – Lion 2012-04-15 18:24:15

+1

您是否嘗試顛倒索引中的列順序? IE瀏覽器。 a_company_id,a_timestamp? – 2012-04-15 18:28:23

回答

1

試圖消除IN子句。它會對整個表格掃描 IN clause中的每個值,導致性能下降。

您可以使用臨時表,用於存儲ID和使用帶有ID在臨時表,而不是使用in條款JOIN,

+0

嗯。這是所有INs的問題還是僅僅在我的特定情況下?在這種情況下,我可以刪除company_id條件並使用PHP進行過濾 - 實際上並不是太多。另外有意思的是,EXPLAIN查詢只顯示1087行... – Salmon 2012-04-15 18:41:05

+0

我不認爲'IN'子句會強制任何表掃描... – 2012-05-22 15:25:59

2

由於翠鳥提到擺脫IN條款(通常是在查詢性能瓶頸)和用JOIN代替它,但不使用臨時表,你這是怎麼做到這一點:

SELECT alerts.* FROM (
    (SELECT 64 AS id) UNION (SELECT 65) UNION (SELECT 69) UNION (SELECT 70) 
    UNION (SELECT 71) UNION (SELECT 72) UNION (SELECT 73) UNION ... 
) AS ids 
INNER JOIN alerts ON (ids.id = alerts.a_company_id) 
WHERE alerts.a_timestamp > '2012-04-15' AND alerts.a_timestamp <= '2012-04-16' 
ORDER BY ids.id DESC 

,並確保你在a_company_id有一個索引。

+0

謝謝,會試試看。時間戳上的單獨索引和單獨的a_company_id? – Salmon 2012-04-15 18:54:38

+0

對於這個查詢,只有'a_company_id'上的索引將很重要我不認爲MySql在'a_timestamp'這裏使用你的索引。 – nobody 2012-04-15 18:57:19

1

嘗試在(a_company_id,a_timestamp)...上創建索引... type_ts_company索引的相反順序。

+0

最終的問題是時間戳記上的範圍查詢無法使用索引,因爲範圍查詢不能很好地進行優化。反轉索引允許company_id IN限制範圍查詢必須查看的值 - 因爲它只需檢查公司ID列表中的值,而不是檢查表中的所有值。 – 2012-06-03 08:26:35

+0

範圍查詢肯定可以使用索引。如果範圍列不是索引關鍵字中的最後一個,則效率不高。如果此數據庫中有成千上萬個company_id,則首先在索引中使用range列,那麼mysql將不得不通過數千個不匹配的company_id進行篩選。但是,如果company_id是第一個,它可以通過對每個單獨的company_id進行範圍搜索。這樣做十幾個比過濾出數以千計的不匹配的記錄要好。 – bobwienholt 2012-06-04 14:00:39