2011-08-19 207 views
3

我有這個users表:MySQL查詢優化需要

id : int (255) 
name: char (100) 
last_comment_target: int(100) 
last_comment_date: datetime 

此表有大約1.3mil行。

PKEYBTREEidlast_comment_targetlast_comment_date

而且,我想執行一系列查詢:

SELECT * FROM users 
WHERE id IN (1,2,3,5,...[around 5000 ids]) 
AND last_comment_target > 0 
ORDER BY last_comment_dt DESC LIMIT 0,20; 

有時查詢可以採取只要3秒鐘。我想知道是否有更好的方法來優化這個查詢。或者,如果這個查詢可以被重寫。

非常感謝您的幫助。

+0

你從哪裏得到5000個ID? – Jacob

+0

5000個ID來自哪裏?如果你可以把它們放到一個表格中(或者它們已經在表格中)並且進行連接,它可能會更快。更好的是,如果5000個ID可以與用戶中的屬性相關聯,那麼您可以將其指定爲簡單條件 - 如果需要,甚至可以對其進行索引。 –

+0

這5000個ID是手動插入還是可以查詢? – AJC

回答

1
SELECT u.* 
FROM 
    users u 
    JOIN (
     SELECT 1 id 
     UNION ALL 
     SELECT 2 id 
     UNION ALL 
     : 
     : 
     SELECT 5000 id 
    ) ids ON ids.id = u.id 
WHERE 
    last_comment_target > 0 
ORDER BY 
    last_comment_dt DESC 
LIMIT 0, 20; 
+0

謝謝。我想知道你能否幫助我解釋一下你的答案。爲什麼我們使用'SELECT 1 id UNION ALL SELECT 2 id UNION ALL ....'作爲'JOIN'的一部分?我們真的可以在我們從另一個表派生的表上做一個'JOIN'嗎?它會有什麼不同(如果有的話)? –

+0

@Heru這將創建一個所有ID的臨時表。連接表通常是一個更快的解決方案,但它取決於很多因素,你應該測試它。如果你有一些其他表中的所有ID,那麼你可以使用你的其他表,而不是這些UNION:'select id from other_table' – Karolis

+0

謝謝@Karolis - 我相信內部連接更好。 –

0

謝謝大家的貢獻。

@Karolis似乎替代使用join代替range

所以,基本上指出:

SELECT * FROM users WHERE id IN (1,2,3,...[5000 ids]) AND last_comment_target > 0

單產EXPLAIN聲明RANGEtype。 5000個ID可以從另一個表中生成。

當我切換上面:

SELECT * 
FROM users u 
INNER JOIN user_friends uf ON u.id = uf.to_id 
AND u.last_comment_target > 0 
AND uf.from_id = [id]; 

它產生於EXPLAIN語句包含兩個typesrefeq_ref這是快於range在此查詢。

查詢執行從3+秒減少到0.2x秒左右。

所以,教訓從我結束瞭解到:TRY使用JOIN而不是RANGE如果你有,你可以從派生表。