2013-05-02 79 views
0

這是一個大約需要5-6秒的查詢。內部只需要大約50毫秒。加快使用WHERE ID的查詢IN

SELECT id,messages.to,messages.from,message,datetime,messages.read 
FROM messages WHERE id IN( //inside brackets grabs a list of IDs 

    SELECT max(messages.id) FROM 
     (SELECT id,messages.from FROM messages 
     WHERE messages.to = 'username' AND messages.from != 'username' 
     UNION 
     SELECT id,messages.to FROM messages WHERE 
     messages.from = 'username' AND messages.to != 'username') 
    AS x 
    LEFT JOIN messages ON messages.id = x.id 
    GROUP BY x.from) 

ORDER BY id DESC 
LIMIT 15 

這是一個查詢,用於獲取某人最近發送過的消息的用戶列表,以及兩者之間的最後一條消息。我如何改變這個以便它更快?也許沒有ID IN。也許多個查詢?

+1

顯示您的表定義。另外運行'EXPLAIN ',這樣你就可以看到每個部件使用的索引。向我們展示'EXPLAIN'的輸出 – Cfreak 2013-05-02 01:44:09

+0

爲什麼你要對消息進行外連接而不是內連接? – 2013-05-02 01:45:35

+0

您的敘述中說:「某人最近一直在發送消息的用戶列表」,但查詢中沒有任何內容將結果過濾爲「某人」。 – 2013-05-02 01:47:31

回答

5

任何查詢可以被轉換爲連接。

在這種情況下,你需要這個查詢從

SELECT * from TABLE where attr IN (SUBQUERY) 

SELECT * from TABLE JOIN (SUBQUERY) AS subTable ON (table.attr = subtable.attr) 

的主要挑戰是不要做子查詢的「for循環」型(轉換這是你所擁有的),因爲對於外部查詢中的每個元組都執行內部查詢。如果你有很多元組,結果就是你有內核查詢很多次。

所以想辦法只是做子查詢一次。例如,在這種情況下,請爲每個消息ID,其最大id(僅執行一次)返回一個查詢,然後加入到原始消息表中。

換句話說,不要以爲for循環。根據你需要加入的組來考慮。

哦,還有一件事我只注意到...怎麼樣在做一個內部查詢(選擇由ID限15從消息訂單ID),並加入這個的消息而不是整個查詢外LIMIT 15。

,如果你有外的限制,查詢將在消息的每條記錄進行評估。如果您將LIMIT移入內部,則DBMS將在執行復雜查詢的其餘部分之前計算前15個值,並且只會執行15次!而不是表中的每個元組。 --dmg

+0

好的提示,兄弟! – 2013-05-02 01:54:34

+0

謝謝!我會試試這個。 – TJE 2013-05-02 02:12:20

相關問題