我想像IM那样从vBulletin中获取所有的PMs,这应该在我的。NET Core库中使用Dapper。 这意味着:A向B发送消息,B回复将是一个带有两条消息的对话。 由于这会导致性能问题,所以我尝试使用DBeaver通过直接运行Dapper查询来解决这个问题。
要从收件箱中获取页面的对话,我编写了以下查询:
SELECT pm.pmid
FROM pm, pmtext AS txt
WHERE pm.pmtextid = txt.pmtextid
AND (pm.userid = 123 OR txt.fromuserid = 123)
AND pm.folderid != -1
GROUP BY IF(pm.parentpmid != 0, pm.parentpmid, pm.pmid)
LIMIT 0, 50
这给了我用户#123的前50个会话ID。 它可以工作,但执行时间约为440ms。 我尝试向所有相关字段添加索引
ALTER TABLE pmtext ADD INDEX fromuserid_only(fromuserid);
ALTER TABLE pm ADD INDEX userid_only(userid);
ALTER TABLE pm ADD INDEX parentpmid(parentpmid);
但还是很慢。 这似乎是由组by
引起的。 即使我只执行按pm.parentpmid
分组(这会产生错误的数据,但只是为了性能测试),查询运行时间也不会更好。 当我通过删除组时,它非常快(12ms)。
我计算对话总页数的查询在没有联接及其快速(<20ms):
// DbConnection db = ...
string sqlTotalPages = @"
SELECT CEIL(COUNT(*)/ 50) AS pages
FROM pm, pmtext AS txt
WHERE pm.pmtextid = txt.pmtextid
AND (pm.userid = 18 OR txt.fromuserid = 18)";
int totalPages = db.QueryFirstOrDefault<int>(sqlTotalPages);
为什么group by
会大大降低查询速度? 我怎样才能提高绩效?
CREATE TABLE `pm` (
`pmid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`pmtextid` int(10) unsigned NOT NULL DEFAULT '0',
`userid` int(10) unsigned NOT NULL DEFAULT '0',
`folderid` smallint(6) NOT NULL DEFAULT '0',
`messageread` smallint(5) unsigned NOT NULL DEFAULT '0',
`parentpmid` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`pmid`),
KEY `pmtextid` (`pmtextid`),
KEY `userid` (`userid`,`folderid`),
KEY `userid_only` (`userid`),
KEY `parentpmid` (`parentpmid`)
) ENGINE=MyISAM AUTO_INCREMENT=221965 DEFAULT CHARSET=latin1
CREATE TABLE `pmtext` (
`pmtextid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fromuserid` int(10) unsigned NOT NULL DEFAULT '0',
`fromusername` varchar(100) NOT NULL DEFAULT '',
`title` varchar(250) NOT NULL DEFAULT '',
`message` mediumtext,
`touserarray` mediumtext,
`iconid` smallint(5) unsigned NOT NULL DEFAULT '0',
`dateline` int(10) unsigned NOT NULL DEFAULT '0',
`showsignature` smallint(5) unsigned NOT NULL DEFAULT '0',
`allowsmilie` smallint(5) unsigned NOT NULL DEFAULT '1',
`reportthreadid` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`pmtextid`),
KEY `fromuserid` (`fromuserid`,`dateline`),
KEY `fromuserid_only` (`fromuserid`),
KEY `fromuserid_only2` (`fromuserid`)
) ENGINE=MyISAM AUTO_INCREMENT=118470 DEFAULT CHARSET=latin1
我认为GROUP BY之所以会导致诸如处理时间的增加是因为限制。 当没有GROUP BY时,DB引擎可以在找到50个符合条件的行后停止处理查询中的行。 使用GROUP BY子句,整个表需要处理,分组在一起,然后返回50个第一个结果。 至于solution,如果删除组BY并在where子句中添加“and pm.parentpmid=0”,会得到正确的结果吗? GROUP BY子句似乎是用来从结果中移除具有父项的行的,使用WHERE可以更有效地完成此操作(假设所有具有父项的行在结果中也具有父项)。