我一直在开发一个小型 Perl 程序,该程序与文章表一起工作,如果尚未阅读,则将它们显示给用户。它一直运行良好,总体而言速度非常快。但是,今天下午,性能已经从足够快的速度下降,以至于我不担心将查询优化到每个查询 3-4 秒的冰期。为了选择文章,我提出了这个查询:
SELECT channelitem.ciid, channelitem.cid, name, description, url, creationdate, author
FROM `channelitem`
WHERE ciid NOT
IN (
SELECT ciid
FROM `uninet_channelitem_read`
WHERE uid = '1030'
)
AND (
cid =117
OR cid =308
OR cid =310
)
ORDER BY `channelitem`.`creationdate` DESC
LIMIT 0 , 100
可能的 cid 列表各不相同,可能更多。无论如何,我注意到进行查询的总时间中大约有 2-3 秒用于“ORDER BY”。如果我删除它,只需要大约半秒的时间就可以将查询返回给我。如果我放弃子查询,性能会恢复正常......但直到今天下午,在正常工作一周左右之后,子查询似乎没有问题。
有什么想法可能会减慢它的速度吗?我可以做些什么来尝试让性能恢复到鼻烟?被查询的表有 45,000 行。子查询的表目前少于 3,000 行。
更新:顺便说一句,如果有人对如何进行多个查询或其他一些更有效地完成我想要做的事情有建议,我会全神贯注。我现在真的很困惑如何解决这个问题。我可以在联接之前以某种方式应用 order by 以使其应用于真实表而不是派生表吗?这样会更有效率吗?
这是查询的最新版本,来自@Gordon 的建议,如下
SELECT channelitem.ciid, channelitem.cid, name, description, url, creationdate, author
FROM `channelitem`
LEFT JOIN (
SELECT ciid, dateRead
FROM `uninet_channelitem_read`
WHERE uid = '1030'
)alreadyRead ON channelitem.ciid = alreadyRead.ciid
WHERE (
alreadyRead.ciid IS NULL
)
AND `cid`
IN ( 6648, 329, 323, 6654, 6647 )
ORDER BY `channelitem`.`creationdate` DESC
LIMIT 0 , 100
另外,我应该提到关于这两个表的数据库结构是什么样的——也许有人会发现这个结构的一些奇怪之处:
CREATE TABLE IF NOT EXISTS `channelitem` (
`newsversion` int(11) NOT NULL DEFAULT '0',
`cid` int(11) NOT NULL DEFAULT '0',
`ciid` int(11) NOT NULL AUTO_INCREMENT,
`description` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
`url` varchar(222) DEFAULT NULL,
`creationdate` datetime DEFAULT NULL,
`urgent` varchar(10) DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`lastchanged` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`author` varchar(255) NOT NULL,
PRIMARY KEY (`ciid`),
KEY `newsversion` (`newsversion`),
KEY `cid` (`cid`),
KEY `creationdate` (`creationdate`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1638554365 ;
CREATE TABLE IF NOT EXISTS `uninet_channelitem_read` (
`ciid` int(11) NOT NULL,
`uid` int(11) NOT NULL,
`dateRead` datetime NOT NULL,
PRIMARY KEY (`ciid`,`uid`),
KEY `ciid` (`ciid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;