MySQL查询改进(Tmp表、发送数据和排序)
我的查询如下所示:MySQL查询改进(Tmp表、发送数据和排序),mysql,performance,Mysql,Performance,我的查询如下所示: 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的用户)发送或接收的所有聊天信息(内部
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的用户)发送或接收的所有聊天信息(内部查询)
此查询在我的服务器上运行非常频繁,并且占用了大量时间(>0.1s
)
phpMyAdmin分析工具显示,复制到tmp表
(我猜这是由内部查询引起的),发送数据
(缺少索引?)占用了约32%的时间,排序结果
描述
查询告诉我它没有使用任何索引(尽管它说有可能的索引)
以下是完整的列表:
有人有线索吗
编辑:
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:我编辑了查询,现在删除了排序结果部分。
虽然发送结果
和复制到tmpo表
的过程仍然需要花费大量时间
EDIT3:再次更改了查询。现在唯一占用大量时间的部分是发送数据
描述
返回以下内容:
编辑4:为Xint0的查询描述
:
运算符或
使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
编辑:查询设计中的逻辑错误。为子查询提供新建议
SELECT *
FROM prv_chat
WHERE 100 IN (Sender, Recipient)
ORDER BY Sent DESC;
这应该适用于您当前检索的内容
此100 IN(发送者,接收者)
位还将使用您的Sender\u 3
键
编辑:您可能还想查看表的InnoDB
引擎正如您在注释中所指出的,问题是使用*
选择所有列。一般建议,如果不需要,尽量不要选择所有列
我建议:
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\u 3
外部查询仅对筛选结果和分组结果排序
编辑
在看到descripe
输出后,g
子查询似乎没有使用Sender\u 3
索引。我建议首先运行analyze table prv\u chat
命令更新索引统计信息,以便MySQL引擎可以基于当前索引覆盖率优化查询。如果这不会导致引擎使用Sender\u 3
索引,则尝试修改它以将ID
作为第一列:(ID,Sender,Recipient,Sent)
EDIT2
我认为临时表和文件排序是由于对聚合结果进行排序造成的。您可以发布prv\u chat
的DDL吗?我将其添加到了第一篇博文中谢谢,这样就消除了排序结果的大部分。但是我在发送数据
(现在是90%)和复制到tmp表
表的行数和这个查询的行数没有限制方面仍然有问题。你能对查询运行descripe并发布结果吗?哦,好吧,这似乎对排序部分也起作用。事实上,我不知道为什么在编写查询时需要这个内部查询,但是没有它它就无法工作。但是你的解决方案也能解决这个问题!但是,当我现在尝试按发送者、接收者对其进行分组时,查询速度又慢了很多(复制到tmp表)。为什么要分组?因为您的查询多次返回相同的发送者-接收者组合。我需要的是最新发送的不同的(发送者,接收者)
在这种情况下,我建议使用WHERE 100 In(发送者,接收者)
而不是初始的或语句,并将其用作子查询tank you,此查询似乎工作得很好:),性能也更好。不过,复制到tmp表
大约需要0.04秒以上的时间。有什么想法吗?--我会马上发布此查询的描述结果谢谢,我尝试了两个新建议,但没有改变任何东西。查询仍未使用索引Sender_3
。