面试官:COUNT(*)、COUNT(1)、COUNT(某一列)的区别是什么?哪个性能更好?

今天,我们讨论一个MySQL查询相关的经典问题,也是大家日常工作经常会用到的。不少同学可能使用了多年的COUNT(*),也不是很清楚它与COUNT(1)、COUNT(某一列)的区别,让我们今天就一探究竟吧。

面试官:COUNT(*)、COUNT(1)、COUNT(某一列)的区别是什么?哪个性能更好?

我们还是先用一张图概述所有要点:

图片

基本概念

1、COUNT(*):

这个表达式会计算表中的所有行,包括那些值为NULL的行。它不考虑列的选择,直接统计整个表的行数。

MySQL官网[1]中有说明:InnoDB通过遍历最小的可用二级索引来处理SELECT COUNT(*)语句,除非索引或优化器提示优化器使用不同的索引。如果二级索引不存在,InnoDB通过扫描聚簇索引来处理SELECT COUNT(*)语句。

为什么要采用遍历最小的可用二级索引,而不是直接选聚簇索引?

因为二级索引不存储具体数据,相比聚簇索引占用空间小,遍历的I/O效率更高。

2、COUNT(1):

这是一个优化过的计数方式,实际上并不计算任何列的值,而是把“1”作为一个常量来对待,统计的是满足条件的行数。这种方式避免了访问表的具体列,理论上可以提高效率,尤其是在列值可为空的情况下。

MySQL官网[1]中有说明:InnoDB处理SELECT COUNT(*)和SELECT COUNT(1)操作的方式相同。

3、COUNT(某一列):

这个表达式统计的是指定列中非NULL值的数量。如果该列有NULL值,那么这些行不会被计入总数中。

区别

1、数据处理范围:

COUNT(*)包括了所有行,无论列值是否为NULL;COUNT(1)同样统计所有行,因为它计数的是恒定的1,不关心行数据的实际内容;而COUNT(某一列)只统计该列非NULL值的行数。

2、性能影响因素:

由于COUNT(*)COUNT(1)不需要访问实际的数据行(特别是当索引可以覆盖查询需求时),它们的执行效率可能高于COUNT(某一列),特别是当该列含有大量NULL值时。

3、应用场景:

如果你需要统计表的所有行数,包括那些具有NULL值的行,应使用COUNT(*)COUNT(1)。若你需要统计特定列的非NULL值数量,则应使用COUNT(某一列)

性能比较

1、在MySQL中,COUNT(*)COUNT(1)的性能差异微乎其微,甚至可以认为是等价的。在MySQL官网中,明确指出InnoDB引擎中两语句性能一致[1]。原文如下:

InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.

2、相比之下,COUNT(某一列)的性能取决于该列的数据分布,特别是NULL值的比例。如果该列包含大量NULL值,且查询优化器无法有效利用索引,那么它的执行效率可能会低于前两者。其中COUNT(主键)相比COUNT(普通列)的性能要好。

3、实际性能还受到数据库索引、表结构、数据量、以及数据库管理系统具体实现等因素的影响。因此,在特定场景下,需进行实际测试。

结语

总的来说,COUNT(*)COUNT(1)在统计全表行数时非常相似,且在多数情况下性能相当,推荐在不需要考虑特定列的NULL值时使用。而COUNT(某一列)则适用于需要精确统计某列非NULL值数量的场景。在考虑性能优化时,了解并利用数据库的特定优化特性和执行计划分析工具,可以帮助做出更合适的选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值