select count(*) 应该是一个比较常用的语句,用来统计记录行数。

但是,慢慢地你会发现,这个语句越来越慢了,为什么呢?

count(*) 的实现方式

首先,我们来看下它的实现方式。

MySQL 中,不同的存储引擎,count(*) 的实现方式是不同的。

1、MyISAM 引擎,表级锁,不需考虑事务,比较简单粗暴,直接将表的总行数存储在磁盘上,因此效率很高;

2、InnoDB 引擎中,行级锁,需要考虑事务,执行时,需要一行行的把数据查出来,然后累加;

为啥 MyISAM 就可以这样做呢?因为它不支持事务啊,不会有并发的数据库行数修改,所以查询得到的行数是准确的,不用担心数据不一致的问题。

而 InnoDB 就不一样了。

由于 MVCC 的存在,InnoDB 在当前执行环境下,对一共有多少数据行是不确定的,比如:

假设,表 t 中有 10000 条数据,有下面三个用户并行的会话:

1、A 启动事务,查询表的总行数;
2、C 直接插入一条数据,然后查询总行数;
3、B 启动事务,插入一条数据,然后查询总行数;
4、C 查询总行数;

注意,上面启动的事务都没有提交。

A、B、C 查询的结果都不相同。

B 读到的是 10002,是因为可重复读隔离级别的存在,而 C 未开启事务,因此无法看到别的事务的更新;

综上,InnoDB 引擎中,在每一个会话中,都需要逐行读取数据,然后计数返回总行数。

InnoDB 对 count(*) 的优化

我们知道,COUNT(*)的目的只是为了统计总行数,所以,他根本不关心自己查到的具体值,所以,他如果能够在扫表的过程中,选择一个成本较低的索引进行的话,那就可以大大节省时间。

InnoDB中索引分为聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值。所以,相比之下,非聚簇索引要比聚簇索引小很多。

MySQL会优先选择最小的非聚簇索引来扫表。所以,当我们建表的时候,除了主键索引以外,创建一个非主键索引还是有必要的。

这种情况下,InnoDB 在执行 count(*) 时,就会判断使用哪个索引,会选择最小的树来进行遍历。

在保证逻辑正确的前提下,尽量减少扫描的数据量,是数据库系统设计的通用法则之一。

小结

1、由于 MyISAM 引擎不需要支持事务,因此可以快速返回 count(*)
2、show table status 命令虽然返回很快,但是不准确;
3、InnoDB 执行 count(*) 时会遍历全表,因此性能较差;

count(*)、count(1)、count(主键)、count(字段)的区别

以下,基于 InnoDB。

含义区别

count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL

count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL

count(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计

性能区别

对于 count(字段)

  1. 如果这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,无需判断为null,按行累加;
  2. 如果这个“字段”定义允许为 null,那么执行的时候,判断到有可能是 null,还要把值取出来再判断一下,不是 null 才累加。

对于 count(主键id),InnoDB 会遍历全表,取每行的主键 id,返回给 server 层,server 层拿到数据后,进行判断累加。

对于 count(1),InnoDB 仍遍历全表,但是不取值,server 层对返回的每一行数据新增一个 1,然后进行判断累加;因此,count(1) 要更快些,因为无需取值。从引擎返回 id 会涉及到解析数据行,以及拷贝字段值的操作。

但是 count(*) 是例外,并不会把全部字段取出来,而是专门做了优化。count(*) 肯定不是 null,按行累加。

结论:按照效率排序的话,count(字段)<count(主键 id)<count(1)≈count(*),所以我建议你,尽量使用 count(*),因为这个是SQL92定义的标准统计行数的语法。

MySQL数据库count语句详解相关推荐

  1. laravel 调试mysql_Laravel - MySQL数据库的使用详解3(Query Builder用法2:新增、修改、删除)...

    五.新增.修改.删除操作 在前文中我介绍了如何使用Query Builder(查询构造器)进行数据查询,下面接着介绍如何使用它进行数据的增.删.改操作.同样假设我们有如下用户表(user): 1,新增 ...

  2. MySQL 数据库 source 命令详解及实例

    MySQL 数据库 source 命令详解及实例 MySQL 数据库 source 命令,该命令是数据库导入命令.source 命令的用法非常简单,首先你需要进入 MySQL 数据库的命令行管理界面, ...

  3. linux系统——mysql数据库默认字符集详解

    linux系统--mysql数据库默认字符集详解 - mysql的字符集配置细化到四种 对数据库server配置 对库设置 对表设置 对列设置 - 对mysql-server设置 对server设置是 ...

  4. 【数据库】MySQL的sql语句详解

    目录 MySQL之sql语句 一, INSERT语句 insert语句的使用: 1,给表中一次性插入一条记录 2,给表中一次性插入多条记录 二, REPLACE语句 REPLACE语句的使用 1,语法 ...

  5. 17@MySQL数据库读现象详解(脏读、幻读、不可重复读)

    文章目录 MySQL数据库读现象 一.数据库的读现象 1.脏读(dirty read):读取未提交数据 [案列详解] 2.不可重复读取 (nonrepeatable read):前后多次读取,数据内容 ...

  6. mysql数据库BKA算法详解

    BKA算法详解 Batched Key Access理解了 MRR 性能提升的原理,我们就能理解 MySQL 在 5.6 版本后开始引入的 BatchedKey Access(BKA) 算法了.这个 ...

  7. MYSQL数据库使用操作详解

    MySQL  客户端版 MySQL Community Server 社区版 开源免费 MySQL的官方网址: http://www.mysql.com/ ,MySQL的社区版本下载地址为: http ...

  8. dbeaver连接mysql 驱动jar_Jmeter(七) 从入门到精通 建立数据库测试计划实战lt;MySQL数据库gt;(详解教程)...

    1.简介 在实际工作中,我们经常会听到数据库的性能和稳定性等等,这些有时候也需要测试工程师去评估和测试,上一篇文章宏哥主要介绍了jmeter连接和创建数据库测试计划的过程,宏哥在文中通过示例和代码非常 ...

  9. java连接mysql数据库方法_java连接mysql数据库的方法详解

    连接mysql数据库在java中有几种常用的方式有官方提供的JDBC连接MySQL数据库也有后面我们讲到的其它的方式连接数据库,具体如下. JDBC连接MySQL数据库 首先要下载Connector/ ...

最新文章

  1. jqplot php,JSON的jqPlot
  2. 部署laravel项目
  3. 全国大学生电工数学建模竞赛赛题_A
  4. 交换机端口镜像(锐捷)
  5. 如何让Visual Studio 2010支持HTML5和CSS3
  6. java添加容器_如何为Java应用程序构建docker容器
  7. andriod studio 运行 无结果_无负压静音供水设备下篇一
  8. android自定义view的实现方法,Android自定义View的实现方法
  9. java c 转换_Java怎么转换c语言?
  10. python程序实现excel排序_python初学—-实现excel里面读数据进行排序(改进算法)
  11. 【报告分享】2021年中国新锐品牌增长潜力报告.pdf(附下载链接)
  12. HashMap分别按照key和value进行排序的快捷方法
  13. python3编译器不同版本差别大吗_python3.9的转义符使用和其他版本不一样吗?
  14. C语言:输入四个数a,b,c,d,将这四个数由小到大排序
  15. 【转】ASP.NET Web应用程序写EventLog出错的解决方案
  16. oracle cogs 科目,CFA一级财报科目:现金流量表详情介绍!
  17. 深度学习——汉字识别
  18. 北航超算运行matlab,北航荣获世界大学生超算总决赛一等奖!超50万亿次,又破世界纪录...
  19. 程序员跳槽时,如何优雅地谈薪水?
  20. 暗金色 rgb_杜伽TAURUS K310樱桃RGB红轴体验:做工精良、手感优秀

热门文章

  1. element el-table(:render-header)实现动态表头的自适应
  2. 微信公众号H5页面中获取openId
  3. linux中如何创建及复制文件/文件夹的软链接?
  4. python樱花_Python画一棵漂亮的樱花树(不同种樱花+玫瑰+圣诞树喔)
  5. 2023大数据、互联网与教育技术国际学术会议(ICBDIET 2023)
  6. 调用阿里云短信接口,报InvalidTimeStamp.Expired : Specified time stamp or date value is expired.错误
  7. 解决:无法连接Java VisualVM 插件中心, 因为Server returned HTTP response code: 503 for URL: http://www.oracle.com/
  8. 在线剪切板、在线拼音输入法
  9. IDEA设置护眼模式
  10. 在VMware workstation上使用win_server_2012(Hyper-v)搭建云桌面教程