一文搞清楚MySQL count(*)、count(1)、count(col)区别


Posted in MySQL onMarch 03, 2022

在工作中遇到count(*)、count(1)、count(col) ,可能会让你分不清楚,都是计数,干嘛这么搞这么多东西。

count 作用

COUNT(expression):返回查询的记录总数,expression 参数是一个字段或者 * 号。

测试

MySQL版本:5.7.29

创建一张用户表,并插入一百万条数据,其中gender字段有五十万行是为null值的

CREATE TABLE `users` (
  `Id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(32) DEFAULT NULL COMMENT '名称',
  `gender` varchar(20) DEFAULT NULL COMMENT '性别',
  `create_date` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`Id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='用户表';

count(*)

在 MySQL 5.7.18 之前,通过扫描聚集索引来InnoDB处理 语句。SELECT COUNT( *)从 MySQL 5.7.18 开始, 通过遍历最小的可用二级索引来InnoDB处理SELECT COUNT( *)语句,除非索引或优化器提示指示优化器使用不同的索引。如果二级索引不存在,则扫描聚集索引。
大概意思就是有二级索引的情况下就使用二级索引,如果有多个二级索引优先选择最小的那个二级索引来降低成本,没有二级索引使用聚集索引。

下面通过测试来验证这些观点。

首先,在只有Id这一个主键索引的情况下查询执行计划,

一文搞清楚MySQL count(*)、count(1)、count(col)区别

可以看到,type是index也就是使用了索引,key是PRIMARY就是使用了主键索引,key_len=8。

其次在name字段上加上索引,再次使用执行计划查看

一文搞清楚MySQL count(*)、count(1)、count(col)区别

可以看到同样使用了索引,只不过索引用的是name字段的索引,key_len=99。

然后在保留name字段索引的情况下给create_date字段也加上索引,再次查看执行计划

一文搞清楚MySQL count(*)、count(1)、count(col)区别

可以看到这次使用的是create_date字段的索引了,key_len=6。

不管上述是使用了哪个索引,其最后查询到的总行数都是一百万条,无论它们是否包含 NULL值。

count(1)

count(1) 和count(*) 执行查询结果一样,最终也是返回一百万条数据,无论它们是否包含 NULL值。

count(col)

count(col) 统计某一列的值,又分为三种情况:

count(id): 统计id

和count(*) 执行查询结果也是一样,最终也是返回一百万条数据.

count(index col):统计带索引的字段

以count(name)进行查询,执行计划如下:

一文搞清楚MySQL count(*)、count(1)、count(col)区别

可以看到用的是索引字段进行统计,索引也命中了。
把一列中的name字段置为NULL,再进行count查询,结果返回999999

一文搞清楚MySQL count(*)、count(1)、count(col)区别

再把这列的NULL值置为空字符串,再进行count查询,结果返回1000000

一文搞清楚MySQL count(*)、count(1)、count(col)区别

所以,综上简单的使用索引字段统计行数能够命中索引,并且只统计不为NULL值的行数。

count(normal col):统计不带索引的字段

统计不带索引的字段的话就不会使用索引,而且也是只统计不为NULL值的行数。

一文搞清楚MySQL count(*)、count(1)、count(col)区别

count(1)和count(*)取舍

之前也不知道在哪看到的或听说的,count(1) 比count(*) 效率高,这是错误的认知,官网上有这么一句话,InnoDB handles SELECT COUNT( *) and SELECT COUNT(1) operations in the same way. There is no performance difference.
翻译过来就是,InnoDB以同样的方式处理SELECT COUNT( *)和SELECT COUNT(1) 操作,没有性能差异。

对于MyISAM表, 如果从一个表中检索,没有检索到其他列并且没有 子句,COUNT(*)则优化为非常快速地返回 ,此优化仅适用于MyISAM 表,因为为此存储引擎存储了准确的行数,并且可以非常快速地访问。 COUNT(1)仅当第一列定义为 时才进行相同的优化NOT NULL。----来自MySQL官网
这些优化都是建立在没有where 和 group by的前提下的。

阿里开发规范中也提到

一文搞清楚MySQL count(*)、count(1)、count(col)区别

所以在开发中能用count(*) 就用count( *).

总结

count(*)、count(1)、count(id):返回查询的记录总数,无论字段是否包含空值,且count( )和count(1)效率是一样的,没差别,通过上面的执行计划可以推断count(id) 和count()、count(1) 效率应该也是一样的或者说是很接近,有兴趣的可以测试一下。
对统计带非主键索引和不带索引的字段进行统计的时候都是统计不为NULL的行数。

到此这篇关于一文搞清楚MySQL count(*)、count(1)、count(col)区别 的文章就介绍到这了,更多相关MySQL count(*),count(1),count(col)内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
MySQL 使用SQL语句修改表名的实现
Apr 07 MySQL
MySQL中InnoDB存储引擎的锁的基本使用教程
May 26 MySQL
SQL注入的实现以及防范示例详解
Jun 02 MySQL
Mysql 如何查询时间段交集
Jun 08 MySQL
mysql优化之query_cache_limit参数说明
Jul 01 MySQL
MySQL对数据表已有表进行分区表的实现
Nov 01 MySQL
MySQL窗口函数的具体使用
Nov 17 MySQL
mysql使用instr达到in(字符串)的效果
Apr 03 MySQL
使用Mysql计算地址的经纬度距离和实时位置信息
Apr 29 MySQL
mysql数据库实现设置字段长度
Jun 10 MySQL
MySQL索引失效场景及解决方案
Jul 23 MySQL
关于MySQL中explain工具的使用
May 08 MySQL
SQL注入篇学习之盲注/宽字节注入
MySQL为数据表建立索引的原则详解
Mar 03 #MySQL
MySQL数据库完全卸载的方法
千万级用户系统SQL调优实战分享
Mar 03 #MySQL
解析MySQL索引的作用
Arthas排查Kubernetes中应用频繁挂掉重启异常
Feb 28 #MySQL
一文搞懂MySQL索引页结构
You might like
简单的php缓存类分享     php缓存机制
2014/01/22 PHP
PHP开发注意事项总结
2015/02/04 PHP
PHP判断一个字符串是否是回文字符串的方法
2015/03/23 PHP
使用XHProf查找PHP性能瓶颈的实例
2017/12/13 PHP
高亮显示web页表格行的javascript代码
2010/11/19 Javascript
JavaScript操作HTML DOM节点的基础教程
2016/03/11 Javascript
JS实现n秒后自动跳转的两种方法
2020/11/30 Javascript
nginx配置React静态页面的方法教程
2017/11/03 Javascript
ES6中数组array新增方法实例总结
2017/11/07 Javascript
jQuery实现下拉菜单动态添加数据点击滑出收起其他功能
2018/06/14 jQuery
vue cli 3.0 使用全过程解析
2018/06/14 Javascript
JavaScript强制类型转换和隐式类型转换操作示例
2019/05/01 Javascript
js动态获取时间的方法分析
2019/08/02 Javascript
微信小程序实现拖拽功能
2019/09/26 Javascript
js实现简易点击切换显示或隐藏
2020/11/29 Javascript
jQuery实现简单轮播图效果
2020/12/27 jQuery
python遍历 truple list dictionary的几种方法总结
2016/09/11 Python
解决python文件字符串转列表时遇到空行的问题
2017/07/09 Python
python opencv之SIFT算法示例
2018/02/24 Python
python3实现磁盘空间监控
2018/06/21 Python
python 利用for循环 保存多个图像或者文件的实例
2018/11/09 Python
django小技巧之html模板中调用对象属性或对象的方法
2018/11/30 Python
python实现图片识别汽车功能
2018/11/30 Python
python requests库爬取豆瓣电视剧数据并保存到本地详解
2019/08/10 Python
将keras的h5模型转换为tensorflow的pb模型操作
2020/05/25 Python
详解Python的爬虫框架 Scrapy
2020/08/03 Python
Jupyter Notebook安装及使用方法解析
2020/11/12 Python
CSS3系列教程:背景图片(背景大小和多背景图) 应用说明
2012/12/19 HTML / CSS
解析HTML5的存储功能和web SQL的相关操作方法
2016/02/19 HTML / CSS
北承题目(C++)
2012/05/16 面试题
经典c++面试题四
2015/05/14 面试题
学校端午节活动方案
2014/08/23 职场文书
离职证明标准格式
2014/09/15 职场文书
MySQL 重命名表的操作方法及注意事项
2021/05/21 MySQL
React配置子路由的实现
2021/06/03 Javascript
JavaScript实现九宫格拖拽效果
2022/06/28 Javascript