我正在尝试构建一个页面,其中显示了成员已收到的消息列表。我提出了这个mySQL查询,但运行速度非常慢。执行它至少需要10秒钟。
SELECT senderid,
receiverid
FROM messages
WHERE ( receiverid, sentdate ) IN (SELECT receiverid,
Max(sentdate)
FROM messages
WHERE receiverid = '1'
GROUP BY senderid)
ORDER BY sentdate DESC
这是我正在使用的数据库:
`autoID` mediumint(11) unsigned NOT NULL AUTO_INCREMENT `senderID` mediumint(11) unsigned DEFAULT '0' `receiverID` mediumint(11) unsigned DEFAULT '0' `sentDate` datetime DEFAULT '0000-00-00 00:00:00' `message` longtext PRIMARY KEY (`autoID`) KEY `receiverID` (`receiverID`) KEY `senderID` (`senderID`)
数据库只有150,000个条目。我正在运行我自己的专用服务器,只有mySQL数据库。
非常感谢任何帮助。
G-Nugget,我在sentDate上添加了一个索引但没有加速。这是EXPLAIN(对不起,显示方式。不知道我还能怎么做):
ID:1个
SELECT_TYPE:PRIMARY
表:消息
类型:ALL
possible_keys:空
键:空
key_len:空
裁判:空
行:149433个
额外:使用在哪里;使用filesort
ID:2
select_type:DEPENDENT SUBQUERY
表:消息
类型:REF
possible_keys:receiverID
关键:receiverID
key_len:4
裁判:常量
行:20个
额外:使用在哪里;使用临时;使用filesort
答案 0 :(得分:1)
这个查询产生你提到的结果集怎么样?
SELECT m.senderid,
m.receiverid
FROM messages m
JOIN (
SELECT max(autoID) autoID,
receiverID, SenderID
FROM messages
GROUP BY receiverId, SenderID
) X on m.autoID = x.AutoId
WHERE m.receiverId = '1'
ORDER BY m.autoID desc
这利用了autoID和sentdate很可能随着时间的推移单调递增的假设。它为每个不同的发送方/接收方对之间的最新消息提取ID,然后使用这些ID选择要显示的消息表的子集。
答案 1 :(得分:0)
在MySQL中,in
的子查询无法正确优化。您的查询有点复杂。我认为这是编写查询的有效方式:
SELECT senderid,
receiverid
FROM messages m
WHERE m.receiverid = '1' and
exists (SELECT 1
FROM messages m1
WHERE m1.receiverid = '1'
GROUP BY m1.senderid
having max(sentdate) = m.sentdate)
ORDER BY sentdate DESC
您的查询似乎正在尝试将每次发送的最新消息发送到“1”。更简单的版本可能是:
select senderid, receiverid
from messages m
where m.receiverid = '1'
也就是说,每个senderid都将包含在您的原始查询中,因为它们的最新发送日期将与in
条件匹配。您可以让两个发件人具有完全相同的日期和时间。是否需要显示这样的副本?