加速使用WHERE id IN的查询

时间:2013-05-02 01:42:59

标签: mysql sql database greatest-n-per-group

这是一个大约需要5-6秒的查询。内部部分只需要大约50毫秒。

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 个答案:

答案 0 :(得分:5)

任何IN查询都可以转换为JOIN。

在这种情况下,您需要从

转换此查询
 SELECT * from TABLE where attr IN (SUBQUERY)

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

主要的挑战是不要执行“for循环”类型的子查询(这是你拥有的),因为对于外部查询中的每个元组,都会执行内部查询。如果你有很多元组,那么结果就是你已经执行了很多次内部查询。

因此,想一想只做一次子查询。例如,在这种情况下,创建一个返回每个消息id的查询,它的最大id(仅执行一次)然后加入原始消息表。

换句话说,不要考虑循环。根据您需要加入的集合进行思考。

哦,还有一件我刚注意到的事情......如何进行内部查询(从id限制15的消息顺序中选择id)并将其连接到消息而不是在整个查询之外使用LIMIT 15。

如果您有限制,则将在消息中为每个元组评估查询。如果您将LIMIT移到内部,DBMS将在执行复杂查询的其余部分之前计算前15个,它将只执行15次!而不是表中的每个元组。 --dmg