我的查询如下:
SELECT Sender, Recipient, Sent
FROM
(SELECT Sender, Recipient, Sent FROM prv_chat WHERE 100 IN (Sender, Recipient))
AS chat
GROUP BY Sender, Recipient
ORDER BY Sent DESC LIMIT 30
它的目的是搜索发送或接收的特定用户(在这种情况下是ID为100的用户)的所有聊天消息(inner query
)
此查询在我的服务器上频繁运行,占用了大量时间(>0.1s
)
phpMyAdmin分析工具显示Copying to tmp table
约占32%的时间(我猜它是由内部查询引起的),Sending data
约占30%(缺少索引?),另有30%由Sorting results
DESCRIBING
查询告诉我它没有使用任何索引(虽然它说有可能的索引)
以下是完整列表:
任何人都有线索?
修改
SHOW CREATE TABLE prv_chat
CREATE TABLE `prv_chat` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Sender` int(9) NOT NULL,
`Recipient` int(9) NOT NULL,
`Chat` text NOT NULL,
`Sent` datetime NOT NULL,
`Read` tinyint(1) NOT NULL,
PRIMARY KEY (`ID`),
KEY `Sender` (`Sender`,`Recipient`),
KEY `Sent` (`Sent`),
KEY `Sender_3` (`Sender`,`Recipient`,`Sent`),
KEY `Sender_2` (`Sender`,`Sent`),
KEY `Recipient` (`Recipient`)
) ENGINE=MyISAM AUTO_INCREMENT=125082 DEFAULT CHARSET=utf8
EDIT2:我编辑了查询,现在sorting results
部分已被删除。
虽然Sending results
和Copying to tmpo table
进度仍然占用了大量时间
EDIT3:再次更改了查询。现在,花费很多时间的唯一部分是Sending data
DESCRIBE
返回此信息:
编辑4: DESCRIBE
:
答案 0 :(得分:0)
运算符OR
使mysql忽略索引。请尝试改为:
SELECT * FROM(
SELECT * FROM prv_chat WHERE Sender=100
UNION ALL
SELECT * FROM prv_chat WHERE Recipient=100
) AS chat
ORDER BY Sent DESC LIMIT 30; --done by hand, may not run
答案 1 :(得分:0)
编辑:查询设计中的逻辑错误。为子查询提供新建议
SELECT *
FROM prv_chat
WHERE 100 IN (Sender, Recipient)
ORDER BY Sent DESC;
这应该适用于您当前正在检索的内容。
此100 IN (Sender, Recipient)
位也会使用您的Sender_3
密钥
编辑:您可能还想查看表格的InnoDB
引擎
答案 2 :(得分:0)
正如您在评论中提到的,问题是使用*
选择所有列。作为一般建议,如果不需要,请尽量不要选择所有列。
我建议:
select Sender, Recipient, MaxSent
from (
select pc.Sender, pc.Recipient, max(pc.Sent) as MaxSent
from
prv_chat pc
inner join (
select ID from prv_chat where Sender = 100
union
select ID from prv_chat where Recipient = 100
) f on pc.ID = f.ID
group by pc.Sender, pc.Recipient
) g
order by MaxSent desc limit 100;
这样,子查询f
会按发件人和收件人过滤ID并使用相应的索引。
然后,发件人,收件人的子查询g
组获取最大发送值,应使用索引Sender_3。
外部查询仅对已过滤和分组的结果进行排序。
修改强>
看到DESCRIBE
输出后,似乎g
子查询未使用Sender_3
索引。我建议首先运行analyze table prv_chat;
命令来更新索引统计信息,以便MySQL引擎可以根据当前索引覆盖率优化查询。如果这不会导致引擎使用Sender_3
索引,请尝试修改它以包含ID
作为第一列:(ID, Sender, Recipient, Sent)
。
<强> EDIT2 强>
我认为临时表和filesort是由聚合结果排序引起的。