【发布时间】:2016-02-18 16:52:01
【问题描述】:
我有一个类似于 Facebook 的通知系统,使用以下 MySQL 语句:
SELECT
n.`id`,n.`content_id`,n.`site_id`,n.`creator_uid`,n.`type`,
nu.`id` AS nuid, nu.`uid` AS nu_uid, nu.`date`,
nr.`id` AS nrid, nr.`uid` AS nr_uid, nr.`is_read`,
u.`gender`
FROM `notification` AS n
LEFT JOIN `notification_user` AS nu ON nu.`nid` = n.`id`
LEFT JOIN `notification_read` AS nr ON nr.`nid` = n.`id`
LEFT JOIN `users` AS u ON u.`id` = nu.`uid`
WHERE
nu.`uid` != '".$_SESSION['uid']."' AND nr.`uid` = '".$_SESSION['uid']."'
OR
(
nu.`uid` = '".$_SESSION['uid']."' AND n.`type` = 'credits'
)
ORDER BY date DESC, nu.`id` DESC
它应该只显示我登录的这个特定用户的通知。但是现在我的通知表上有超过 22500 条记录,而且我总是收到“超出最大执行时间”错误。
我能否以某种方式更改此查询以减少获取所需记录的时间?也许删除连接并执行更多查询?
编辑:添加表格概览
CREATE TABLE IF NOT EXISTS `notification` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content_id` int(11) NOT NULL,
`site_id` int(11) NOT NULL,
`creator_uid` int(11) NOT NULL,
`type` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=22759 ;
.
CREATE TABLE IF NOT EXISTS `notification_read` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nid` int(11) NOT NULL,
`uid` int(11) NOT NULL,
`is_read` tinyint(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `nid` (`nid`),
KEY `nid_2` (`nid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=45342 ;
.
CREATE TABLE IF NOT EXISTS `notification_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nid` int(11) NOT NULL,
`uid` int(11) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=22813 ;
【问题讨论】:
-
使用
explain select ...查看执行计划并将表的索引添加到问题中 -
我想你是通过主键加入的。你的表中有索引吗? n.type 可以被索引。但是22500条记录并不多。
-
@Kiwi Juicer:每个
id字段都被索引为主键。 @juergen d:我现在真的不知道该怎么做,也不知道应该在哪里做。我可以在 PhpMyAdmin 中这样做吗? -
只需要加入性别的用户表吗?可能按 id 而不是日期排序?
-
@RolandStarke:是的。我还删除了这个,看看这是否花费了太多时间,但它没有改变任何东西。
标签: php mysql left-join jointable