MySQL 中 count(*) 和 count(1) 有什么区别?哪个性能最好?

count 是一个函数,用来统计数据,但是 count 函数传入的参数有很多种,比如 count(1)、count(*)、count(字段) 等,哪个性能最好呢?是不是count(*)就是性能最差呢?

先说个结果吧:

count(*)=count(1)>count(主键)>count(name)

上面的结论是建立在 innodb 存储引擎上的,下面说明为什么。

就拿 user_aiyoumi表做说明,主键:user_id,二级索引:idx_createtime

count(*) 其实统计的就是全表的数据条数,会被sql优化器优化成count(0),如果表中有二级索引的话会优化走二级索引。

MySQL 中 count(*) 和 count(1) 有什么区别?哪个性能最好?_第1张图片 count(1) 与count(*)是一样的

MySQL 中 count(*) 和 count(1) 有什么区别?哪个性能最好?_第2张图片

count(name) 这个是统计name不为null的记录条数,不会走索引,遍历了所有的记录

MySQL 中 count(*) 和 count(1) 有什么区别?哪个性能最好?_第3张图片

count(主键) 这也是统计所有的记录条数的,也有可能会被优化器优化走二级索引的。

count(二级索引) 统计二级索引不为空的记录条数

count(主键字段) 执行过程是怎样的?

InnoDB 是通过 B+ 树来保持记录的,根据索引的类型又分为聚簇索引和二级索引,它们区别在于,聚簇索引的叶子节点存放的是实际数据,而二级索引的叶子节点存放的是主键值,而不是实际数据。

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

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

读取数据是耗io的,一级索引里面含有一行的全部数据,io上相对来说是比较慢的;二级索引就不一样,存储的是二级索引与一级索引的关系,io相对会快很多。但优化器一般会把count(主键)优化走二级索引,说到这大家就很清楚了:

走(二级索引)>走(主键)

下面user_id为主键,这里看出count(主键)走了二级索引。

MySQL 中 count(*) 和 count(1) 有什么区别?哪个性能最好?_第4张图片

 

count(name)查找的是name不为null的数据,也就是说查出来后,在判断下是否为null,那效率就会再低一些。

count(主键)>count(name)

整体下来执行效率就为:前提是由二级索引的情况下:

count(*)=count(1)>count(主键)>count(name)

这里强调一点,count(主键)有可能也会被优化器走二级索引的。其他的存储引擎又不一样了,MyISAM的count就是单独维护了一个count变量,count仅仅O(1)

你可能感兴趣的:(mysql,数据库,后端,database)