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