mysql中count(*)、count(1)、count(主键)、count(字段)的区别

文章目录

以下分析都是基于 select count(?) from table 这个语句来分析,不带过滤条件。

count函数的语义

count() 是一个聚合函数,函数的参数不仅可以是字段名,也可以是其他任意表达式,该函数作用是统计符合查询条件的记录中,函数指定的参数不为 NULL 的记录有多少个。

在通过 count 函数统计有多少个记录时,MySQL 的 server 层会维护一个名叫 count 的变量。

server 层会循环向 InnoDB 读取一条记录,如果 count 函数指定的参数不为 NULL,那么就会将变量 count 加 1,直到符合查询的全部记录被读完,就退出循环。最后将 count 变量的值发送给客户端。

count(主键)

在通过 count 函数统计有多少个记录时,MySQL 的 server 层会维护一个名叫 count 的变量。

server 层会循环向 InnoDB 读取一条记录,如果 count 函数指定的参数不为 NULL,那么就会将变量 count 加 1,直到符合查询的全部记录被读完,就退出循环。最后将 count 变量的值发送给客户端。

如果表里只有主键索引,没有二级索引时

那么,InnoDB 循环遍历聚簇索引,将读取到的记录返回给 server 层,然后读取记录中的 id 值,根据 id 值判断是否为 NULL,如果不为 NULL,就将 count 变量加 1。

如果表里有二级索引时

InnoDB 循环遍历的对象就不是聚簇索引,而是二级索引。

这是因为相同数量的二级索引记录可以比聚簇索引记录占用更少的存储空间,所以二级索引树比聚簇索引树小,这样遍历二级索引的 I/O 成本比遍历聚簇索引的 I/O 成本小,因此「优化器」优先选择的是二级索引。

count(1)

如果表里只有主键索引,没有二级索引时

InnoDB 循环遍历聚簇索引(主键索引),将读取到的记录返回给 server 层,但是不会读取记录中的任何字段的值,因为 count 函数的参数是 1,不是字段,所以不需要读取记录中的字段值。参数 1 很明显并不是 NULL,因此 server 层每从 InnoDB 读取到一条记录,就将 count 变量加 1。

可以看到,count(1) 相比 count(主键字段) 少一个步骤,就是不需要读取记录中的字段值,所以通常会说 count(1) 执行效率会比 count(主键字段) 高一点。

*** 如果表里有二级索引时***

InnoDB 循环遍历的对象就二级索引。

count(*)

当你使用 count() 时,MySQL 会将 * 参数转化为参数 0 来处理,也就是说 count() 其实等于 count(0)。

所以,count(*) 执行过程跟 count(1) 执行过程基本一样的,性能没有什么差异。

而且 MySQL 会对 count(*) 和 count(1) 有个优化,如果有多个二级索引的时候,优化器会使用key_len 最小的二级索引进行扫描。

只有当没有二级索引的时候,才会采用主键索引来进行统计。

count(字段)

count(字段) 的执行效率相比前面的 count(1)、 count(*)、 count(主键字段) 执行效率是最差的。主要原因是因为它是个全表扫描操作。

替代方案

explain或者show table status

如果对于count值不是要求很精确可以通过执行 explain或者show table status来获取值

中间表或者其他数据库计数

如果要求比较精确可以在写数据后通过中间表或者其他数据库去记录当前数量。

相关推荐
看天走路吃雪糕1 小时前
墨者:SQL注入实战-MySQL
数据库·mysql·base64·sql注入·sqlmap·墨者靶场·tamper
程序猿小D1 小时前
Java项目:基于SSM框架实现的进销存管理系统【ssm+B/S架构+源码+数据库+毕业论文+远程部署】
java·数据库·mysql·ssm·jsp·毕业论文·进销存管理系统
小王子10242 小时前
Django模型开发:模型字段、元数据与继承全方位讲解
mysql·django·模型
九转苍翎4 小时前
全面解析MySQL(4)——三大范式与联合查询实例教程
mysql
什么半岛铁盒4 小时前
MySQL的常用数据类型详解
linux·数据库·mysql·adb
rannn_1114 小时前
【MySQL学习|黑马笔记|Day1】数据库概述,SQL|通用语法、SQL分类、DDL
数据库·后端·学习·mysql
Antonio9155 小时前
【MySQL】MySQL 缓存方案
数据库·mysql·缓存
越来越无动于衷7 小时前
基于 JWT 的登录验证功能实现详解
java·数据库·spring boot·mysql·mybatis
看天走路吃雪糕7 小时前
墨者:SQL手工注入漏洞测试(MySQL数据库-字符型)
数据库·mysql·sql注入·sqlmap·墨者学院·字符型注入