MySQL 中 count(*) 比 count(1) 快?
Java后端技术
共 3207字,需浏览 7分钟
·
2021-12-30 07:59
往期热门文章:
count(1)
比 count(*)
快,这能忍?必须得和他掰扯掰扯。1.实践
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. explain 分析
type:前三个的 type 值为 index,表示全索引扫描,就是把整个索引过一遍就行(注意是索引不是整个表);后两个的 type 值为 all,表示全表扫描,即不会使用索引。 key:这个表示 MySQL 决定采用哪个索引来优化对该表的访问,PRIMARY 表示利用主键索引,NULL 表示不用索引。 key_len:这个表示 MySQL 使用的键长度,因为我们的主键类型是 INT 且非空,所以值为 4。 Extra:这个中的 Using index 表示优化器只需要通过访问索引就可以获取到需要的数据(不需要回表)。
3. 原理分析
3.1 主键索引与普通索引
3.2 原理分析
select count(1) from user;
这个查询来说,InnoDB 引擎会去找到一个最小的索引树去遍历(不一定是主键索引),但是不会读取数据,而是读到一个叶子节点,就返回 1,最后将结果累加。select count(id) from user;
这个查询来说,InnoDB 引擎会遍历整个主键索引,然后读取 id 并返回,不过因为 id 是主键,就在 B+ 树的叶子节点上,所以这个过程不会涉及到随机 IO(并不需要回表等操作去数据页拿数据),性能也是 OK 的。select count(username) from user;
这个查询来说,InnoDB 引擎会遍历整张表做全表扫描,读取每一行的 username 字段并返回,如果 username 在定义时候设置了 not null,那么直接统计 username 的个数;如果 username 在定义的时候没有设置 not null,那么就先判断一下 username 是否为空,然后再统计。select count(*) from user;
,这个 SQL 的特殊之处在于它被 MySQL 优化过,当 MySQL 看到 count(*)
就知道你是想统计总记录数,就会去找到一个最小的索引树去遍历,然后统计记录数。explain select count(*) from user;
的执行计划:4. MyISAM 呢?
select count(*) from user;
操作执行起来是非常快的,那是因为 MyISAM 把表中的行数直接存在磁盘中了,需要的时候直接读取出来就行了,所以非常快。
往期热门文章:
1、《历史文章分类导读列表!精选优秀博文都在这里了!》 2、程序员裸辞全职接单一个月的感触 3、Java8 Stream:2万字20个实例,玩转集合的筛选、归约、分组、聚合 4、字节终面:两个文件的公共URL怎么找? 5、留在一线,逃离一线?我从上海举家回成都的生活经历告诉你 6、公司规定所有接口都用 POST请求,这是为什么? 7、我被这个浏览了 746000 次的问题惊住了! 8、腾讯三面:40亿个QQ号码如何去重? 9、自从用完Gradle后,有点嫌弃Maven了!速度贼快! 10、一个员工的离职成本有多恐怖!
评论