MySql - 添加 Order by 时查询缓慢
Posted
技术标签:
【中文标题】MySql - 添加 Order by 时查询缓慢【英文标题】:MySql - Slow Query when adding Order by 【发布时间】:2021-06-23 06:01:24 【问题描述】:我有一个从 mysql 数据库读取电子邮件的应用程序(我从应用程序数据库中的 gmail 收件箱下载电子邮件)。并且数据库具有以下结构
表 1(联系人):
ContactID (int)
ContactName (varchar(100)
ContactEmailAddress (varchar(150))
表2(科目):
SubjectID (int)
ContactID (int)
Subject (varchar(200))
Table3(消息):
MessageID (int)
SubjectID (int)
MessageText (varchar(150)
IsRead (tinyint)
IsReceived (tinyint)
MessageDate (DateTime)
这是我获取最近 40 条记录的查询
SELECT * FROM(SELECT ROW_NUMBER()OVER(Order by isRead ASC,MessageDate DESC) RecID,
c.ContactName,s.subject,s.SubjectID,d.MessageDate,d.isRead
from Contacts c
INNER JOIN Subjects s on s.ContactID=c.ContactID
JOIN (
select MAX(MessageID) dtl_id,SubjectID from Messages where IsReceived=1
GROUP BY SubjectID)d_max on (d_max.subjectid=s.subjectid)
JOIN Messages d on (d.MessageID=d_max.dtl_id)
) AS RowConstrainedResult where RecID >=1 and RecID <=40 ORDER BY RecID
但此查询需要将近 15 秒才能加载。应该做些什么来提高查询性能。因为我的所有主键列和引用的键列都被索引了。 Messages 表中有近 50 万条记录。
【问题讨论】:
显示带有数据类型、索引和执行计划的表模式。 我已经更新了数据类型,我不能在这里共享表模式。所有整数字段都被索引。执行计划可以看这里ibb.co/pPFFJpZ 请说明查询的目的。并提供EXPLAIN SELECT ...
。并提供SHOW CREATE TABLE
(我们需要查看索引等)。
show index from tablename
你能用详细的解释计划显示输出吗
@RickJames 查询的目标是获取最近的 40 封未读邮件。我将尝试解释一下,假设我们在联系人表中有 2 个电子邮件地址,email1@mydomain.com 和 email2@yourdomain.com。并且他们俩在 Messages 表中都有 10 条消息。现在假设 email2@yourdomain.com 在 DB 中有第二条消息处于未读状态,而 emial1 在 DB 中有第一条处于未读状态的消息,所以 email1 将显示在顶部。解释结果可以在ibb.co/FbPs3SD查看
【参考方案1】:
你提供的链接中的EXPLAIN
好像不是你提供的SELECT
,所以我不得不忽略它。
这个索引可能会有所帮助:
Messages: (IsReceived, SubjectID, MessageID)
我添加了标签[groupwise-maximum]
。它链接到许多其他正在做类似事情的问题。很少有人真正成功地优化了任务。我在这里比较了最快的技术:http://mysql.rjweb.org/doc.php/groupwise_max
【讨论】:
谢谢,添加建议的索引将查询执行时间从 12 秒减少到 5 秒以下.. 5 秒对于 UI 来说仍然很糟糕。查看我的链接和/或标签。 是的,你是对的,但仍然比 12 或 13 秒要好。我确实检查了链接,看来我必须对我的数据库架构进行一些小改动才能将其缩短到 2 到 3 秒。以上是关于MySql - 添加 Order by 时查询缓慢的主要内容,如果未能解决你的问题,请参考以下文章
MySQL ORDER BY 根据日期时间查询返回不正确的结果