【问题标题】:mysql "group by" very slow querymysql“分组依据”非常慢的查询
【发布时间】:2010-10-26 16:23:01
【问题描述】:

我在一个大约有 10 万条记录的表中有这个查询,它运行速度很慢(3-4 秒),当我取出组时它要快得多(不到 0.5 秒)。我很茫然如何解决这个问题:

SELECT msg.id,
       msg.thread_id,
       msg.senderid,
       msg.recipientid, 
       from_user.username AS from_name,
       to_user.username AS to_name
FROM msgtable AS msg
LEFT JOIN usertable AS from_user ON msg.senderid = from_user.id
LEFT JOIN usertabe AS to_user ON msg.recipientid = to_user.id
GROUP BY msg.thread_id
ORDER BY msg.id desc

msgtable 在thread_ididsenderidrecipientid 上有索引。

解释返回:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  msg ALL NULL    NULL    NULL    NULL    162346  Using temporary; Using filesort
1   SIMPLE  from_user   eq_ref  PRIMARY PRIMARY 4   db.msg.senderid 1    
1   SIMPLE  to_user eq_ref  PRIMARY PRIMARY 4   db.msg.recipientid  1

任何想法如何在返回相同结果的同时加快速度(每个线程有多条消息,我想在此查询中每个线程只返回一条消息)。

提前致谢。

【问题讨论】:

  • usertable 索引呢?你能运行EXPLAIN <query> 并发布结果吗?
  • 通常,您必须在 GROUP BY 中声明未由聚合函数(COUNT、SUM、MIN、MAX 等)封装的 SELECT 中提到的所有列。在这种情况下,DISTINCT 会更好地为您服务吗?
  • 为什么是左连接?不是每封邮件都需要收件人和发件人吗?
  • 是的,邮件需要收件人和发件人,因此不需要左加入。
  • 另外,粘贴show create table msgtable的输出。

标签: sql mysql sql-optimization


【解决方案1】:

试试这个:

select m.thread_id, m.id, m.senderid, m.recipientid, 
       f.username as from_name, t.username as to_name
from msgtable m
join usertable f on m.senderid = f.id
join usertable t on m.recipientid = t.id
where m.id = (select MAX(id) from msgtable where thread_id = m.thread_id)

或者这个:

select m.thread_id, m.id, m.senderid, m.recipientid, 
       (select username from usertable where id = m.senderid) as from_name,
       (select username from usertable where id = m.recipientid) as to_name
from msgtable m
where m.id = (select MAX(id) from msgtable where thread_id = m.thread_id)

为什么用户表保持连接?邮件是否可以缺少发件人或收件人?..

【讨论】:

  • 感谢一百万,我尝试了两种选择 - 第一个选项大约 1.5 秒,第二个选项大约 2 秒。我还能做些什么来降低它?
  • @Sherif 好吧,您真的需要同时使用所有线程吗?...是否有一个 datetime 列可用于减少所需数据?
  • @Forsco,实际上这个查询被翻译成一个分页类查询的选择计数(*) - 是的,我需要所有线程,因为这是一个管理功能......
  • @Sherif 那么您需要真实数据还是只需要计数?还是将结果缓存然后分页?
  • @Sherif 好的,正在检查。很高兴我们能够缩短时间,但不确定我能否为您做更多事情。
【解决方案2】:

最大的问题是msgtable 上没有可用的索引。在至少senderidrecipientid 上创建一个索引,它应该有助于加快查询速度,因为它会限制需要扫描的结果数量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2020-08-14
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多