mysql count(*) count(1) count(具体字段)的解析

count(1) 会统计null值,因为1 != null
count(*) 会统计nullcount(field) 若field为null,则不会统计


在分析三个count之前,我们需要知道,一张表在没有主键索引的情况,mysql底层还是为表设置一个隐藏索引,这是由innodb的ibd文件的
物理特性决定的。在知道上面这点之后,故我们知道,无论一张表是只有一个主键索引还是没有任何索引,都是会去遍历聚簇索引的,这
就导致需要扫描所有的记录。

情况1 一张表是只有一个主键索引或没有任何索引且field允许为空
	count(field)<count(1)=count(*)count(1)count(*)不必多说都需要遍历全表且统计null值,count(field)效率低是因为field
	允许为空,则在遍历聚簇索引的时候,mysql还需要去判断field是否为空,造成了额外开销

情况2 一张表是只有一个主键索引或没有任何索引且field不允许为空
	count(field)=count(1)=count(*)count(field)与前两者效率相等是因为,这次遍历,不再需要对field进行空值判断了

情况3 一张表除了主键索引外,还有其他索引
	假设有一张表
	CREATE TABLE `pet` (
	  `id` bigint,
	  `name` varchar(255),
	  `age` int,
	  PRIMARY KEY (`id`),
	  KEY `idx_name` (`name`)
	);

	这时,mysql优化器当统计记录数的时候,会面临两个索引选择 primary key和idx_name
	当count(*),count(1),count(id),count(name),mysql优化器走的都是idx_name索引,因为这个成本最低,那么原因是什么呢?
	一个聚簇索引,数据页中,每条记录都包括着该记录的所有字段,既然一行记录变大了,该数据页总大小不变默认为16KB,故能容纳的
	记录条数就变少了,则需要更多的数据页来存放记录,造成了额外的IO一个二级索引,数据页中,每条记录只包括着该记录的某几个字段,
	例如idx_name索引,数据页中的一条记录只包括着name和id字段,一条记录变小了,则数据页能容纳的记录条数就变多了则只需要更少的
	数据页来存放记录,减少了IO

	所以当面临两个索引可以走的时候,mysql大部分情况下会选择二级索引来统计记录数,除了某些field在二级索引中并不存在,
	例如count(age),表中没有age对应的二级索引,故mysql还是会去扫描全表的



结论:
	上边儿的分析只针对innodb,大部分情况下,count(*)count(1)总是相等的,count(field)效率可能<=前边儿两者,
	因为field可能不存在索引或field允许为空需要造成额外的空值判断;
	myisam中,count(*)永远效率最高,因为myisam底层维护着一个count变量来记录记录数,只有count(*)才能触发;
	结合上边儿来看,count(*)是最好的选择
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值