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

FeH*_*ora 18 php mysql performance

我有一个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
Run Code Online (Sandbox Code Playgroud)

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

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

B)选择max(ID)发件人或收件人为我的邮件。
(如果max(ID)>大于以前的数字,则有新消息)

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

Kai*_*aii 16

在MySQL InnoDB中,这SELECT COUNT(*) WHERE secondary_index = ?是一项昂贵的操作,并且当用户有很多消息时,此查询可能需要很长时间。即使使用索引,引擎仍需要对所有匹配记录进行计数。随着总消息数的增加,性能将下降。

另一方面,SELECT MAX(id) WHERE secondary_index = ?通过在索引的B-Tree结构中进行简单的向下钻取,可以在几乎恒定的时间内交付该索引中的最高id。

如果您想了解原因,请考虑查找B + Tree数据结构的工作方式,InnoDB使用它来存储其数据。

我建议你去用SELECT MAX(id),如果要求是只检查是否有邮件(不他们的计数)。

另外,如果您依赖消息计数,则可能会在竞争条件上留下空白。如果用户删除一条消息并在两个轮询间隔之间收到一条新消息,该怎么办?

  • 如果在a上有一个索引,则从tbl WHERE a = constant处的SELECT MAX(id)使用所谓的“松散索引扫描”。这些几乎快得惊人。从tbl的SELECT COUNT(*)那里a = constant进行*紧密索引扫描,*并没有那么快。 (5认同)
  • “SELECT MAX(id) 将始终使用主索引” - 是的,除非在未编入索引的字段上有 `where` 的情况。 (2认同)