【发布时间】:2020-06-14 08:50:02
【问题描述】:
我想像 IM 一样从 vBulletin 中获取所有 PM,这应该在我的 .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。它有效,但执行时间约为 440 毫秒。我尝试向所有相关字段添加索引
ALTER TABLE pmtext ADD INDEX fromuserid_only(fromuserid);
ALTER TABLE pm ADD INDEX userid_only(userid);
ALTER TABLE pm ADD INDEX parentpmid(parentpmid);
但它仍然很慢。这似乎是由GROUP BY 引起的。即使我只是做GROUP BY pm.parentpmid(这会产生错误的数据,但只是为了性能测试),查询运行时间也不会更好。当我删除 GROUP BY 时,它非常快(~12ms)。
我的计算对话总页数的查询在没有连接的情况下是相似的,而且速度很快(
// 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 会大大降低查询速度?如何提高性能?
vB 中的表结构
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
【问题讨论】:
-
速度取决于几个因素。数据存储在一个文件中,因此有几个因素是速度 1)您使用的微型计算机的速度 2)正在使用的磁盘的速度 3)使用密钥等数据的组织 4)数据库的碎片
-
你考虑过 A) ALTER TABLE pm ADD INDEX pm_parentmid_and_pmid ( parentpmid,pmid);和 B) 删除现有的 parentpmid 以避免出现冗余索引。 C) 将 BOTH != 更改为 > 以获得索引中的正起点?
标签: c# mysql asp.net-core mariadb vbulletin