2009-06-09 137 views
1

我一直在努力優化我的查詢,看起來像一個:MySQL的UNION VS IN子句

select toc.* from 
    (select sender, max(convid) as maxconvid 
    from MetaTable 
    where sender in ('arjunchow','aamir_alam') 
    group by sender) as tmp1 
    inner join MetaTable as toc on 
     toc.sender = tmp1.sender 
     and toc.convid = tmp1.maxconvid; 

當MySQL服務器是在壓力下,這個查詢通常0.2秒內響應,但是當數IN子句中的「發件人」ID增加(> 50),查詢速度變慢(約5-6秒)。

考慮到我的查詢可能成爲50個查詢的聯合,建議使用多個聯合子句而不是IN子句。所以我的查詢將如下所示:

(SELECT 
    convId, 
    UNIX_TIMESTAMP(timeStamp) as timeStamp, 
    UNIX_TIMESTAMP(createTime) as createTime, 
    numMessages, 
    rootMsg, 
    sender, 
    ipormobile, 
    modIpOrMobile, 
    UNIX_TIMESTAMP(modTimeStamp) as modTimeStamp 
from 
    MetaTable 
where 
    sender='arjunchow' 
ORDER BY convId DESC limit 1) 
UNION ALL 
(SELECT 
    convId, 
    UNIX_TIMESTAMP(timeStamp) as timeStamp, 
    UNIX_TIMESTAMP(createTime) as createTime, 
    numMessages, 
    rootMsg, 
    sender, 
    ipormobile, 
    modIpOrMobile, 
    UNIX_TIMESTAMP(modTimeStamp) as modTimeStamp 
from 
    MetaTable 
where 
    sender='aamir_alam' 
ORDER BY convId DESC limit 1) 
+0

EXPLAIN輸出會很好。 – 2009-06-09 10:18:44

回答

0

重寫查詢如下:

SELECT * 
FROM MetaTable 
WHERE (sender, convid) IN 
     (
     SELECT sender, MAX(convid) as maxconvid 
     FROM MetaTable 
     WHERE sender IN ('arjunchow','aamir_alam') 
     GROUP BY 
       sender 
     ) 

,請確保您在(sender, convid)有一個綜合指數,並確保它的使用(即沒有在解釋USING INDEX FOR GROUP BY計劃)

1

我有一個類似的問題與標籤搜索,實際上有機會與MySQL技術人員談論它;他們建議我創建一個臨時表並在您循環訪問用戶時添加我的值,然後在該臨時表上執行任何需要的操作。任何時候你試圖將這麼多東西包裝到一個命令中,它會嚴重陷入困境。