* mysql中count和count(1)哪个效率高?( 二 )


 
如果你使用过show table status 命令的话 , 就会发现这个命令的输出结果里面也有一个rows值用于显示这个表当前有多少行 。
 
那么是不是这个rows值就能代替count(*)了吗?
其实不能 , rows这个是从从采样估算得来的 , 因此它也是不是准确 。不准确到什么程度 , 官方文档说是在40%到50% 。所以show table status命令显示的行数rows是不能直接使用 。

* mysql中count和count(1)哪个效率高?

文章插图
 
基于MySQL的Innodb存储引擎 , 统计表的总记录数下面这4种做法 , 哪种效率最高?
实践案例 , 准备了一张有 500W多条数据的表 , 表结构如下:
 
CREATE TABLE `tb_user` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`user_id` int(11) DEFAULT NULL ,`user_name` varchar(100) DEFAULT NULL ,PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `userId` (`user_id`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4可以看到 , 这张表有一个主键索引 , 用不同方式来查询该表用户记录总数
  • count(主键id)
用select count(*) from tb_user 耗时0.739s
InnoDB引擎会遍历整张表 , 把每一行的id值都取出来 , 返回给server层 。server层拿到id后 , 判断是不可能为空的 , 就按行累加 。
  • count(1)
用select count(1) from tb_user 耗时0.753s
同样遍历整张表 , 但不取值 , server层对返回的每一行 , 放一个数字1进去 , 判断是不可能为空的 , 按行累加 。
  • count(字段)
用select count(user_name) from tb_user 耗时1.436s
分为两种情况 , 字段定义为not null和null
  1. 为not null时:逐行从记录里面读出这个字段 , 判断不能为null , 累加
  2. 为 null时:执行时 , 判断到有可能是null , 还要把值取出来再判断一下 , 不是null才累加
 
  • count(*)
 
用select count(*) from tb_user 耗时0.739s
需要注意的是 , 并不是带了*就把所有值取出来 , 而是mysql做了专门的优化 , count(*)肯定不是null , 按行累加 。
从上面的执行结果 , 得知count(字段)<count(主键id)<count(1)≈count(*)
总结基于MySQL的Innodb存储引擎 , 统计表的总记录数按照效率排序的话count(字段)<count(主键id)<count(1)≈count(*)
效率最高是count(*),并不是count(1)
所以建议尽量使用count() 。
如果有面试官问你mysql中count(*)和count(1)哪个效率高?你就可以明确地告诉他 , Innodb存储引擎下效率最高是count(*) 。
由于笔者知识水平有限,文中错漏之处在所难免,如有不足之处 , 欢迎纠正 , 感谢 。




推荐阅读