【发布时间】:2016-04-14 10:43:18
【问题描述】:
我有一个聊天应用程序。我有一个 api,它返回用户交谈的用户列表。但是当达到100000行数据时,mysql返回列表消息需要很长时间。 这是我的消息表
CREATE TABLE IF NOT EXISTS `messages` (
`_id` int(11) NOT NULL AUTO_INCREMENT,
`fromid` int(11) NOT NULL,
`toid` int(11) NOT NULL,
`message` text NOT NULL,
`attachments` text NOT NULL,
`status` tinyint(1) NOT NULL DEFAULT '0',
`date` datetime NOT NULL,
`delete` varchar(50) NOT NULL,
`uuid_read` varchar(250) NOT NULL,
PRIMARY KEY (`_id`),
KEY `fromid` (`fromid`,`toid`,`status`,`delete`,`uuid_read`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=118561 ;
这是我的用户表(简化)
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`login` varchar(50) DEFAULT '',
`sex` tinyint(1) DEFAULT '0',
`status` varchar(255) DEFAULT '',
`avatar` varchar(30) DEFAULT '0',
`last_active` datetime DEFAULT NULL,
`active` tinyint(1) DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=15523 ;
这是我的查询(对于 id 为 1930 的用户)
select SQL_CALC_FOUND_ROWS `u_id`, `id`, `login`, `sex`, `birthdate`, `avatar`, `online_status`, SUM(`count`) as `count`, SUM(`nr_count`) as `nr_count`, `date`, `last_mesg` from
(
(select `m`.`fromid` as `u_id`, `u`.`id`, `u`.`login`, `u`.`sex`, `u`.`birthdate`, `u`.`avatar`, `u`.`last_active` as online_status, COUNT(`m`.`_id`) as `count`, (COUNT(`m`.`_id`)-SUM(`m`.`status`)) as `nr_count`, `tm`.`date` as `date`, `tm`.`message` as `last_mesg` from `messages` as m inner join `messages` as tm on `tm`.`_id`=(select MAX(`_id`) from `messages` as `tmz` where `tmz`.`fromid`=`m`.`fromid`) left join `users` as u on `u`.`id`=`m`.`fromid` where `m`.`toid`=1930 and `m`.`delete` not like '%1930;%' group by `u`.`id`)
UNION
(select `m`.toid as `u_id`, `u`.`id`, `u`.`login`, `u`.`sex`, `u`.`birthdate`, `u`.`avatar`, `u`.`last_active` as online_status, COUNT(`m`.`_id`) as `count`, 0 as `nr_count`, `tm`.`date` as `date`, `tm`.`message` as `last_mesg` from `messages` as m inner join `messages` as tm on `tm`.`_id`=(select MAX(`_id`) from `messages` as `tmz` where `tmz`.`toid`=`m`.`toid`) left join `users` as u on `u`.`id`=`m`.`toid` where `m`.`fromid`=1930 and `m`.`delete` not like '%1930;%' group by `u`.`id`)
order by `date` desc ) as `f` group by `u_id` order by `date` desc limit 0,10
请帮助优化此查询
我需要什么, 用户与谁交谈(姓名、性别等) 最后一条消息是什么(来自我或给我) 消息数(全部) 未读消息计数(仅限我)
查询运行良好,但耗时太长。
输出一定是这样的
【问题讨论】:
-
您没有提供
EXPLAIN的输出。每个与 MySQL 相关的问题都有。从我所看到的 - 你正在做一个LIKE在开头和结尾使用通配符的查询 - 这表示全表扫描(因此它会遍历表的整个数据)。没有提到配置,所以我们不知道 MySQL 是否可以正确利用您的硬件。从问题来看,您正在运行默认配置,在机械驱动器上,没有任何优化,如果您必须执行LIKE搜索以获取 id =1930的用户的数据,那么您查询它完全错误我害怕。 -
我用输出图片编辑了问题。当用户删除消息时,我正在添加“user_id+分号”来删除列。所以在查询中有“
m.deletenot like '%1930;%'”。所以删除的消息不会被检索。 -
您使用 LIKE 运算符引用的删除列的目的是什么?如果那是删除消息的用户的 ID,它应该是一个 INT单独的连接表来保存这些 ID。
-
如果您删除该条件,查询也需要很长时间。但我会用单独的表格测试已删除的消息。您还有其他建议吗?
标签: mysql large-data