简体   繁体   English

选择耗时8秒。 改善想法

[英]select taking 8 seconds. improve ideas

I have this select to get chat (like facebook inbox). 我选择此选项来聊天(例如Facebook收件箱)。 It will show most recent messages, grouping by user who sent them. 它将显示最新消息,并按发送消息的用户分组。

SELECT c.id, c.from, c.to, c.sent, c.message, c.recd FROM chat c 
WHERE c.id IN(
  SELECT MAX(id) FROM chat
  WHERE (`to` = 1 and `del_to_status` = '0') or (`from` = 1 and `del_from_status` = '0')
  GROUP BY CASE WHEN 1 = `to` THEN `from` ELSE `to` END
)
ORDER BY id DESC
limit 60

The problem is it is taking about 8 seconds. 问题是这大约需要8秒钟。

`chat` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `from` int(11) UNSIGNED NOT NULL,
  `to` int(11) UNSIGNED NOT NULL,
  `message` text NOT NULL,
  `sent` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `recd` tinyint(1) NOT NULL DEFAULT '0',
  `del_from_status` tinyint(1) NOT NULL DEFAULT '0',
  `del_to_status` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `from` (`from`),
  KEY `to` (`to`),
  FOREIGN KEY (`from`) REFERENCES cadastro (`id`),
  FOREIGN KEY (`to`) REFERENCES cadastro (`id`)
)

在此处输入图片说明

any ideas of indexing or re-writing this select to get better speed? 有什么想法索引或重写此选择以获得更快的速度?

I am assuming chat.id is indexed. 我假设chat.id已建立索引。 If not, of course you should add an index. 如果没有,您当然应该添加一个索引。

If it is indexed, MySQL is often very slow with sub selects. 如果已建立索引,则MySQL的子选择速度通常很慢。

One thing you can do is convert your sub select to a temporary table and join with it. 您可以做的一件事是将您的子选择转换为临时表并与之联接。

It will look something like 它看起来像

    CREATE TEMPORARY TABLE IF NOT EXISTS max_chat_ids
                ( INDEX(id) ) 
                ENGINE=MEMORY
                AS ( 'SELECT MAX(id) as id FROM chat
  WHERE (`to` = 1 and `del_to_status` = '0') or (`from` = 1 and `del_from_status` = '0')
  GROUP BY CASE WHEN 1 = `to` THEN `from` ELSE `to` END' );

then, you need to just join with the temp table: 然后,您只需加入临时表:

SELECT c.id, c.from, c.to, c.sent, c.message, c.recd FROM chat c 
join max_chat_ids d on c.id=d.id
ORDER BY c.id DESC
limit 60

temp tables only live during the duration of the session, so if you test this in phpmyadmin remember to execute both queries together with ';' 临时表仅在会话期间有效,因此,如果在phpmyadmin中进行测试,请记住将两个查询与';'一起执行 between them. 它们之间。

If you try this share your result. 如果您尝试此共享您的结果。

I'll assume the column id is already indexed since it probably is the primary key of the table. 我假设列id已被索引,因为它可能是表的主键。 If it's not the case, add the index: 如果不是这种情况,请添加索引:

create index ix1_chat on chat (id);

Then, if the selectivity of the subquery is good then an index will help. 然后,如果子查询的选择性很好,那么索引将有所帮助。 The selectivity is the percentage of rows the select is reading compared to the total number of rows. 选择性是select正在读取的行数占总行数的百分比。 Is it 50%, 5%, 0.5%? 是50%,5%,0.5%? If it's 5% or less then the following index will help: 如果等于或小于5%,则以下索引将有所帮助:

create index ix2_chat on chat (`to`, del_to_status, `from`, del_from_status);

As a side note, please don't use reserved words for column names: I'm talking about the from column. 附带说明,请不要在列名中使用保留字:我说的是from列。 It just makes life difficult for everyone. 这只会使每个人的生活变得困难。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM