加速使用WHERE id IN的查询

TJE*_*TJE 0 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
Run Code Online (Sandbox Code Playgroud)

这是一个查询,它会提取最近有人发送消息的用户列表,以及两者之间的最后一条消息.我怎样才能更改它以便更快?也许没有id IN.也许多个查询?

dmg*_*dmg 5

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

在这种情况下,您需要转换此查询

 SELECT * from TABLE where attr IN (SUBQUERY)
Run Code Online (Sandbox Code Playgroud)

  SELECT * from TABLE JOIN (SUBQUERY) AS subTable ON (table.attr = subtable.attr)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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