2015-07-10 90 views
0

我有一個MySQL數據庫表,具有以下形式:如何優化我的MySQL Select查詢?

CREATE TABLE IF NOT EXISTS data_packet (
    id BIGINT NOT NULL AUTO_INCREMENT, 
    time_received BIGINT NOT NULL, 
    content TEXT NOT NULL, 
    recording_id INT NOT NULL, 
    PRIMARY KEY (id), 
    INDEX fk_data_packet_recording_idx (recording_id ASC), 
    CONSTRAINT fk_data_packet_recording 
    FOREIGN KEY (recording_id) 
    REFERENCES recording(id) 
) 

這個表我有數據,如這裏面:

<Dat url="vehicleSpeed"> 
    <Abs name="speed" val="97"/> 
    <Enm name="unit" val="kmh"/> 
    <Enm name="state" val="valid"/> 
</Dat> 

表最多可包含1,000,000行。現在我有如下的查詢,選擇具有特定URL的特殊數據包。每個數據包都有這樣一個url屬性。

SELECT * 
FROM data_packet 
WHERE recording_id = 1 
    AND content LIKE '%vehicleSpeed%' 
    AND time_received BETWEEN 1435843095338 AND 1435843095996 
ORDER BY time_received ASC; 

我認爲這個星座可以優化。在MySQL工作臺中,該查詢需要47ms,其中表只包含大約35.000行。 Java應用程序應該在稍後執行查詢,並且我注意到,需要更多時間通過JDBC來執行查詢。

您可以推薦哪種優化? 索引?另一列?另一張桌子?

非常感謝。

+0

'time_received'上沒有索引肯定會有幫助 –

+0

您如何製作額外的列,我可以將url分開存儲?指數有什麼影響? – tellob

+0

你可以爲表'id'在列上設置'Unique'約束。由於您已經完成了NOT NULL AUTO INCREMENT,所以您可以應用此約束來提高性能。 – ChiranjeeviIT

回答

0

任何查詢優化縮略規則都表示您可能希望按照相同的順序將INDEX放入where子句中。我建議創建一個帶有兩列(content,time_received)的INDEX,然後使用mySQL中的EXPLAIN命令檢查性能。

ALTER TABLE data_packet 
    ADD INDEX `IDX_COMPOSITE` (content,time_received); 

EXPLAIN SELECT * 
FROM data_packet 
WHERE recording_id = 1 
    AND content LIKE '%vehicleSpeed%' 
    AND time_received BETWEEN 1435843095338 AND 1435843095996 
ORDER BY time_received ASC; 

也儘量不排序

EXPLAIN SELECT * 
FROM data_packet 
WHERE recording_id = 1 
    AND content LIKE '%vehicleSpeed%' 
    AND time_received BETWEEN 1435843095338 AND 1435843095996 

感謝 阿南特

+0

我試圖改變表,並得到以下錯誤:錯誤代碼:1170.密鑰規範中使用的BLOB/TEXT列'內容'沒有密鑰長度 – tellob

+0

尋找一個很好的解釋http://stackoverflow.com/問題/ 1827063/mysql-error-key-specification-without-a-key-length –

+0

是否有意義使3個索引用於:time_received,content,time_received + content?(也許內容然後被一個額外的列替換爲只存儲url) – tellob

0

您對recording_id索引,但你沒有一個還包括列time_received。根據recording_id的數量和覆蓋時間範圍的不同,這可能會產生重大差異。

添加一個包含recording_id和time_received的索引。

第二個主要問題是您的查詢使用LIKE,與具有前導通配符的值進行比較。沒有索引來幫助解決這個問題。您可以嘗試使用FULLTEXT索引,然後使用MATCH()... AGAINST嘗試查找匹配的值。

但是,我會建議它可能會更好地重組您的數據庫。但這很大程度上取決於存儲在內容字段中的數據片段。如果它們全部包含url字段,那麼我可能只是將它存儲在內容字段中(因此您可以直接檢查它而不需要if),然後將其他字段存儲在另一個表中,您可以將它們加入到data_packet表。