COUNT(id) 或 MAX(ID) - 哪个更快?

2022-08-30 20:04:10

我有一个Web服务器,我已经实现了我自己的消息传递系统。我正处于需要创建一个API来检查用户是否有新消息的阶段。

我的数据库表很简单:

ID - Auto Increment, Primary Key (Bigint)
Sender - Varchar (32) // Foreign Key to UserID hash from Users DB Table
Recipient - Varchar (32) // Foreign Key to UserID hash from Users DB Table
Message - Varchar (256) //UTF8 BIN

我正在考虑制作一个API,用于估计给定用户是否有新消息。我正在考虑使用以下方法之一:

A) 选择发件人或收件人为我的邮件。
(如果此号码>以前的号码,我有新消息)count(ID)

B)选择发件人或收件人是我的消息。
(如果 max(ID) >比以前的数字多,我有一条新消息)max(ID)

我的问题是:我能以某种方式计算出什么方法会消耗更少的服务器资源吗?还是有一些文章?也许另一种我没有提到的方法?


答案 1

在MySQL InnoDB中,这是一个昂贵的操作,当用户有很多消息时,此查询可能需要很长时间。即使使用索引,引擎仍然需要计算所有匹配的记录。性能将随着邮件总数的增加而降低。SELECT COUNT(id) WHERE secondary_index = ?

另一方面,通过在索引的 B 树结构中执行简单的钻取,可以在几乎恒定的时间内提供该索引中的最高 id。SELECT MAX(id) WHERE secondary_index = ?

如果您想了解原因,请考虑查找B +Tree数据结构的工作原理,InnoDB使用它来构建表和索引的行。

我建议你去 ,如果要求只是检查是否有消息(而不是它们的计数)。SELECT MAX(id)

此外,如果您依赖于消息计数,则可能会为争用条件打开一个缺口。如果用户删除了一条消息,并在两个轮询间隔之间收到一封新消息,该怎么办?


答案 2

要获得某人有新消息的信息 - 正是这样做的。在系统中记录新消息时更新表中的字段(我假设这是名称)。您拥有收件人的ID,这就是您所需要的。您可以创建一个触发器(假设:有表),该触发器使用布尔标志更新用户表,指示存在消息。usersafter insertusers2messages

这种方法比计算索引(无论是主要索引还是辅助索引)要快得多。当用户执行操作时,您可以在收到新消息时使用 更新表 - 使用 更新表。它很简单,它有效,它可以扩展,并使用触发器来维护它,使它变得简单和无缝。我敢肯定会有不喜欢触发器的反对者,你可以在将用户与新消息相关联时手动执行此操作。usershas_messages = 0has_messages = 1


推荐