COUNT(1)\COUNT(*)\COUNT(列名)到底谁更快

今天来研究一个比较有趣的话题,关于我们平常使用mysql查询数量的到底那种方式查询效率更高的问题

起因

这个问题在我以前的认知里是,按效率从高到低品排序 count(1)>count(列名)>count(*),但是我也注意到过mybatis-plus官方提供的selectCount方法和分页查询时,它的SQL在查询时默认使用的是count(*)其实我对这个问题是一直不解的,我认为mybatis-plus应该不会采取一种效率更低的方式来实现,所以有时间懒研究一下这个问题

现实排名

在性能方面COUNT(*)是约等于COUNT(1)的,COUNT(列名)略低于前两种

原因

关于COUNT函数,在MySQL官网中有详细介绍:

翻译过来就是:COUNT(expr) ,返回SELECT语句检索的行中expr的值不为NULL的数量。结果是一个BIGINT值。如果查询结果没有命中任何记录,则返回0, 但是COUNT(*) 的统计结果中,会包含值为NULL的行数。

MySQL官方对COUNT(*)的优化

COUNT(*)是SQL92定义的标准统计行数的语法,所以MySQL数据库对他进行过很多优化。

MySQL中比较常用的执行引擎就是InnoDB和MyISAM。MyISAM和InnoDB有很多区别,其中有一个关键的区别和我们接下来要介绍的COUNT(*)有关,那就是MyISAM不支持事务,MyISAM中的锁是表级锁;而InnoDB支持事务,并且支持行级锁。
1.因为MyISAM的锁是表级锁,所以同一张表上面的操作需要串行进行,所以,MyISAM做了一个简单的优化,那就是它可以把表的总行数单独记录下来,如果从一张表中使用COUNT(*)进行查询的时候,可以直接返回这个记录下来的数值就可以了,当然,前提是不能有where条件。

MyISAM之所以可以把表中的总行数记录下来供COUNT(*)查询使用,那是因为MyISAM数据库是表级锁,不会有并发的数据库行数修改,所以查询得到的行数是准确的。但是,对于InnoDB来说,就不能做这种缓存操作了,因为InnoDB支持事务,其中大部分操作都是行级锁,所以可能表的行数可能会被并发修改,那么缓存记录下来的总行数就不准确了。
但是,InnoDB还是针对COUNT(*)语句做了些优化的。

在InnoDB中,使用COUNT(*)查询行数的时候,不可避免的要进行扫表了,那么,就可以在扫表过程中下功夫来优化效率了。
从MySQL 8.0.13开始,针对InnoDB的SELECT COUNT(*) FROM tbl_name语句,确实在扫表的过程中做了一些优化。前提是查询语句中不包含WHERE或GROUP BY等条件。我们知道,COUNT(*)的目的只是为了统计总行数,所以,他根本不关心自己查到的具体值,所以,他如果能够在扫表的过程中,选择一个成本较低的索引进行的话,那就可以大大节省时间。我们知道,InnoDB中索引分为聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值。

所以,相比之下,非聚簇索引要比聚簇索引小很多,所以MySQL会优先选择最小的非聚簇索引来扫表。所以,当我们建表的时候,除了主键索引以外,创建一个非主键索引还是有必要的。

结论,MySQL数据库对于COUNT(*)的优化,这些优化的前提都是查询语句中不包含WHERE以及GROUP BY条件。


COUNT(1)与COUNT(*)对比

这个官方文档也有提到

对于COUNT(1)和COUNT(*),MySQL的优化是完全一样的,根本不存在谁比谁快!

建议使用COUNT(*)!因为这个是SQL92定义的标准统计行数的语法

COUNT(字段)

他的查询就比较简单粗暴了,就是进行全表扫描,然后判断指定字段的值是不是为NULL,不为NULL则累加。相比COUNT(*),COUNT(字段)多了一个步骤就是判断所查询的字段是否为NULL,所以他的性能要比COUNT(*)慢。

相关推荐

  1. MYSQL--count(*) 和 count(1)和count()区别

    2024-05-11 16:32:04       51 阅读
  2. count(*) 和 count(1)和count()区别

    2024-05-11 16:32:04       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-11 16:32:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-11 16:32:04       101 阅读
  3. 在Django里面运行非项目文件

    2024-05-11 16:32:04       82 阅读
  4. Python语言-面向对象

    2024-05-11 16:32:04       91 阅读

热门阅读

  1. 并查集刷题笔记

    2024-05-11 16:32:04       30 阅读
  2. postgres 查看全部数据库

    2024-05-11 16:32:04       31 阅读
  3. 数据库的一些知识点

    2024-05-11 16:32:04       30 阅读
  4. 阿里云的ALB和NLB的区别

    2024-05-11 16:32:04       27 阅读
  5. Mybatis报错解决

    2024-05-11 16:32:04       33 阅读
  6. 2024数维杯数学建模竞赛C题思路代码和论文分析

    2024-05-11 16:32:04       55 阅读
  7. Redis当中用StringRedisTemplate封装好的工具类

    2024-05-11 16:32:04       30 阅读
  8. 【Python】Python中assert语句的用法

    2024-05-11 16:32:04       32 阅读
  9. Python: 日期和时间格式化

    2024-05-11 16:32:04       32 阅读