如果你使用过show table status 命令的话 , 就会发现这个命令的输出结果里面也有一个rows值用于显示这个表当前有多少行 。
那么是不是这个rows值就能代替count(*)了吗?
其实不能 , rows这个是从从采样估算得来的 , 因此它也是不是准确 。不准确到什么程度 , 官方文档说是在40%到50% 。所以show table status命令显示的行数rows是不能直接使用 。
文章插图
基于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)
InnoDB引擎会遍历整张表 , 把每一行的id值都取出来 , 返回给server层 。server层拿到id后 , 判断是不可能为空的 , 就按行累加 。
- count(1)
同样遍历整张表 , 但不取值 , server层对返回的每一行 , 放一个数字1进去 , 判断是不可能为空的 , 按行累加 。
- count(字段)
分为两种情况 , 字段定义为not null和null
- 为not null时:逐行从记录里面读出这个字段 , 判断不能为null , 累加
- 为 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(*) 。
由于笔者知识水平有限,文中错漏之处在所难免,如有不足之处 , 欢迎纠正 , 感谢 。
推荐阅读
- Mysql统计近30天的数据,无数据的填充0
- 贵族茶道源自闽潮功夫茶
- 遗传雀斑怎样内调淡化
- 中国茶道的渊源与发展史
- 佛教对中国茶道的贡献
- 茶艺表演的历史发展
- 中国茶艺的形成
- 中国禅宗茶道的介绍
- 预防脑卒中,小小“信号”你必须要当心
- 茶艺赛中展示宋代分茶茶艺