mysql语句性能分析(聊聊MySQL的COUNT*的性能)
mysql语句性能分析
聊聊MySQL的COUNT*的性能前言
基本职场上的程序员用来统计数据库表的行数都会使用count(*),count(1)或者count(主键),那么它们之间的区别和性能你又是否了解呢?
其实程序员在开发的过程中,在一张大表上统计总行数是非常耗时的一个操作,那么我们应该用哪个方法统计会更快呢?
接下来我们就来聊一聊mysql中统计总行数的方法和性能。
count(*),count(1),count(主键)哪个更快?
1、建表并且插入1000万条数据进行实验测试:
|
# 创建测试表 create table `t6` ( `id` int (11) not null auto_increment, ` name ` varchar (50) not null , `status` tinyint(4) not null , primary key (`id`), key `idx_status` (`status`) ) engine=innodb default charset=utf8; # 创建存储过程插入1000w数据 create procedure insert_1000w() begin declare i int ; set i=1; while i<=10000000 do insert into t6( name ,status) values ( 'god-jiang-666' ,1); set i=i+1; end while; end ; #调用存储过程,插入1000万行数据 call insert_1000w(); |
2、分析实验结果
|
# 花了0.572秒 select count (*) from t6; |
|
# 花了0.572秒 select count (1) from t6; |
|
# 花了0.580秒 select count (id) from t6; |
|
# 花了0.620秒 select count (*) from t6 force index ( primary ); |
从上面的实验我们可以得出,count(*)和count(1)是最快的,其次是count(id),最慢的是count使用了强制主键的情况。
下面我们继续测试一下它们各自的执行计划:
|
explain select count (*) from t6; show warnings; |
|
explain select count (1) from t6; show warnings; |
|
explain select count (id) from t6; show warnings; |
|
explain select count (*) from t6 force index ( primary ); show warnings; |
从上面的实验可以得出这三点:
- count(*)被mysql查询优化器改写成了count(0),并选择了idx_status索引
- count(1)和count(id)都选择了idx_statux索引
- 加了force index(primary)之后,走了强制索引
这个idx_status就是相当于是二级辅助索引树,目的就是为了说明: innodb在处理count(*)的时候,有辅助索引树的情况下,会优先选择辅助索引树来统计总行数。
为了验证count(*)会优先选择辅助索引树这个结论,我们继续来看看下面的实验:
|
# 删除idx_status索引,继续执行 count (*) alter table t6 drop index idx_status; explain select count (*) from t6; |
从以上实验可以得出,删除了idx_status这个辅助索引树,count(*)就会选择走主键索引。所以结论:count(*)会优先选择辅助索引,假如没有辅助索引的存在,就会走主键索引。
为什么count(*)会优先选择辅助索引?
在mysql5.7.18之前,innodb通过扫描聚集索引来处理count(*)语句。
从mysql5.7.18开始,innodb通过遍历最小的可用二级索引来处理count(*)语句。如果不存在二级索引,则扫描聚集索引。
新版本为何会使用二级索引来处理count(*)呢?
因为innodb二级索引树的叶子节点上存放的是主键,而主键索引树的叶子节点存放的是整行数据,所以二级索引树比主键索引树小。因此查询优化器基于成本考虑,优先选择的是二级索引。所以索引count(*)快于count(主键)。
总结
这篇文章的结论就是count(*)=count(1)>count(id)。
为什么count(id)走了主键索引还会更慢呢?因为count(id)需要取出主键,然后判断不为空,再累加,代价更高。
count(*)是会总计出所有not null和null的字段,而count(id)是不会统计null字段的,所以我们在建表的尽量使用not null并且给它一个默认是空即可。
最后,在以后总计数据库表的总行数的时候,可以大胆的使用count(*)或者count(1)。
参考资料
- 《高性能mysql》(第三版)第六章优化count()查询
- 《mysql实战45讲》林晓斌
到此这篇关于聊聊mysql的count(*)的性能的文章就介绍到这了,更多相关mysql count(*)内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
原文链接:https://blog.csdn.net/weixin_37686415/article/details/109755245
- mysql读写分离同步策略(Mysql主从复制与读写分离图文详解)
- iis6双php版本的设置(云主机IIS7.5支持PHP5.3以上版本和MYSQL)
- mysql索引应该注意的地方(关于MySQL索引知识的小妙招)
- mysql查看执行计划
- 在mysql语法中用来修改数据的命令(explain命令为什么可能会修改MySQL数据)
- mysql char和varchar区别(MySQL CHAR和VARCHAR存储、读取时的差别)
- mysql缓存是什么(详解mysql查询缓存简单使用)
- mysql建立分区表指令(MySQL高级特性——数据表分区的概念及机制详解)
- mysql substr函数的用法(MySQL切分函数substring的具体使用)
- 如何查看mysql慢查询日志(MySQL慢查询如何定位详解)
- 阿里云mysql升级注意事项(阿里云mysql空间清理的方法)
- mysql默认的事务隔离级别是哪一种(MySql学习笔记之事务隔离级别详解)
- mysql存储过程遍历数据(Mysql 存储过程中使用游标循环读取临时表)
- mysql子查询用法(MySQL 子查询和分组查询)
- mysql分区表的优缺点(MySQL数据表分区策略及优缺点分析)
- mysql中timestamp类型的CURRENT_TIMESTAMP 和ON UPDATE CURRENT_TIMESTAMP属性
- 这个全椒人被通报表彰,看看你认识吗(这个全椒人被通报表彰)
- 全椒人,38年集体回忆 1980-2018 ,看完不要哭(全椒人38年集体回忆)
- 董元奔吟咏历代文人 1012新旧均可 全椒人张璪 1022 -1093(董元奔吟咏历代文人)
- 泪目 这位 刷屏 的英雄,是全椒人的骄傲(泪目这位刷屏)
- 人从众 火炎焱 全椒再现 正月十六走太平 的魅力(人从众火炎焱全椒再现)
- 官宣 全椒籍明星许海峰 奚秀兰 方芳 王璐瑶携手回家 走太平(全椒籍明星许海峰)
热门推荐
- mvc中使用uploadify批量上传
- iframe嵌入页面跨域(使用iframe+postMessage实现页面跨域通信的示例代码)
- 获取当前URL的controller、action
- centos如何安装mysql8.0版本(Centos7下安装MySQL8.0.23的步骤小白入门级别)
- html怎么去除css边框(Html/CSS前端实现文字边框阴影效果)
- 阿里云和腾讯云服务器哪个好些(如何提升阿里云和腾讯云服务器速度)
- SQLServer获取临时表所有列名或是否存在指定列名的方法(SQLServer获取临时表所有列名或是否存在指定列名的方法)
- windows server下的iis配置小结(Windows中IIS内FTP服务器高级配置图文教程)
- mysqlset用法(mysql descDESCRIBE命令实例讲解)
- Ext.MessageBox.show()的用法及参数配置
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9