当前位置: 首页 > 科技观察

再说说MySQL的COUNT的性能,怎么可能是最快的呢?

时间:2023-03-16 13:48:32 科技观察

前言职场基础程序员都会用count(*),count(1)或者count(primarykey)来统计数据库表的行数,那么你了解它们之间的区别和性能吗?事实上,在开发过程中,统计一个大表的总行数对于程序员来说是一个非常耗时的操作。那么我们应该使用哪种方法来更快地统计行数呢?下面说一下MySQL中统计总行数的方法和性能。count(*),count(1),count(primarykey),哪个更快?1、建表插入1000万条数据进行实验测试:#createtesttableCREATETABLE`t6`(`id`int(11)NOTNULLAUTO_INCREMENT,`name`varchar(50)NOTNULL,`status`tinyint(4)NOTNULL,PRIMARYKEY(`id`),KEY`idx_status`(`status`))ENGINE=InnoDBDEFAULTCHARSET=utf8;#创建存储过程插入1000w条数据CREATEPROCEDUREinsert_1000w()BEGINDECLAREiINT;SETi=1;WHILEi<=10000000DOINSERTIINTOt6(name,status)VALUES('god-jiang-666',1);SETi=i+1;ENDWHILE;END;#调用存储过程,插入1000万行数据callinsert_1000w();2.分析实验结果#耗时0.572秒selectcount(*)fromt6;此处插入图片描述#耗时0.572秒selectcount(1)fromt6;#耗时0.580秒selectcount(id)fromt6;#耗时0.620秒selectcount(*)fromt6forceindex(primary);从上面的实验我们可以得出,count(*)和count(1)是最快的,其次是count(id),最慢的是count使用强制主键条件。下面继续测试他们各自的执行计划:explainselectcount(*)fromt6;showwarnings;explainselectcount(1)fromt6;showwarnings;explainselectcount(id)fromt6;showwarnings;explainselectcount(*)fromt6forceindex(primary);showwarnings;从上面的实验中得到这三个可以得出几点:count(*)被mysql查询优化器重写成count(0),count(1)和count(id)都选择了idx_status索引,都选择了idx_statux索引和加力索引(primary)之后,强制索引的idx_status就相当于二级辅助索引树。目的是说明:InnoDB在处理count(*)时,如果有辅助索引树,会优先使用辅助索引树统计总行数。为了验证count(*)会优先辅助索引树的结论,我们继续看下面的实验:#删除idx_status索引,继续执行count(*)altertablet6dropindexidx_status;explainselectcount(*)fromt6;从上面的实验可以得出结论,删除idx_status这棵辅助索引树后,count(*)会选择取主键索引。所以结论:count(*)会优先使用辅助索引,如果没有辅助索引,则使用主键索引。为什么count(*)更喜欢辅助索引?在MySQL5.7.18之前,InnoDB通过扫描聚簇索引来处理count(*)语句。从MySQL5.7.18开始,InnoDB通过遍历最小的可用二级索引来处理count(*)语句。如果不存在二级索引,则扫描聚簇索引。为什么新版本要使用二级索引来处理count(*)?因为InnoDB二级索引树的叶子节点存放的是主键,而主键索引树的叶子节点存放的是整行数据,所以二级索引树比主键索引树小。因此,基于成本的考虑,查询优化器更倾向于使用二级索引。所以索引count(*)比count(primarykey)快。总结这篇文章的结论就是count(*)=count(1)>count(id)。为什么在没有主键索引的情况下count(id)会更慢?因为count(id)需要先取出主键,然后判断不为空,再累加,比较费时。count(*)会统计所有的NOTNULL和NULL字段,而count(id)不会统计NULL字段,所以我们在建表的时候尽量使用NOTNULL,并给它一个默认的空值。最后,以后在总结数据库表的总行数的时候,可以大胆的使用count(*)或者count(1)。参考《高性能MySQL》(第三版)第6章优化COUNT()查询《MySQL实战45讲》林晓斌

最新推荐
猜你喜欢