我一直在研究一个小的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行。
更新:顺便说一句,如果有人建议如何进行多次查询或其他一些技术来更有效地完成我想要做的事情,那么我很满意。我真的很困惑如何在这一点上解决问题。我可以以某种方式在联接之前应用顺序使其应用于真实表而不是派生表吗?这会更有效吗?
这是查询的最新版本,源自@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;
答案 0 :(得分:1)
问题可能是您需要在channelitem表上为列创建日期创建索引。索引可帮助数据库更快地运行查询。以下是有关MySQL Indexing
的链接答案 1 :(得分:1)
尝试此类查询的left outer join
版本绝不会受到伤害:
SELECT ci.ciid, ci.cid, ci.name, ci.description, ci.url, ci.creationdate, ci.author
FROM `channelitem` ci left outer join
(SELECT ciid
FROM `uninet_channelitem_read`
WHERE uid = '1030'
) cr
on ci.ciid = cr.ciid
where cr.ciid is null and
ci.cid in (117, 308, 310)
ORDER BY ci.`creationdate` DESC
LIMIT 0 , 100
uninet_channelitem_read(ciid)
上的索引以及channelitem(cid, ciid, createddate)
上的索引可以加快此查询。