2009-06-09 100 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技术人员谈论它;他们建议我创建一个临时表并在您循环访问用户时添加我的值,然后在该临时表上执行任何需要的操作。任何时候你试图将这么多东西包装到一个命令中,它会严重陷入困境。