0

这是一个大约需要 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。也许多个查询?

4

1 回答 1

5

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

在这种情况下,您需要将此查询从

 SELECT * from TABLE where attr IN (SUBQUERY)

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

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

所以想办法只做一次那个子查询。例如,在这种情况下,进行查询,返回每个消息 id、其最大 id(仅执行一次),然后加入原始消息表。

换句话说,不要考虑 for 循环。考虑你需要加入的集合。

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

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

于 2013-05-02T01:52:58.593 回答