MySQL数据库count语句详解
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(字段)
:
- 如果这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,无需判断为null,按行累加;
- 如果这个“字段”定义允许为 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语句详解相关推荐
- laravel 调试mysql_Laravel - MySQL数据库的使用详解3(Query Builder用法2:新增、修改、删除)...
五.新增.修改.删除操作 在前文中我介绍了如何使用Query Builder(查询构造器)进行数据查询,下面接着介绍如何使用它进行数据的增.删.改操作.同样假设我们有如下用户表(user): 1,新增 ...
- MySQL 数据库 source 命令详解及实例
MySQL 数据库 source 命令详解及实例 MySQL 数据库 source 命令,该命令是数据库导入命令.source 命令的用法非常简单,首先你需要进入 MySQL 数据库的命令行管理界面, ...
- linux系统——mysql数据库默认字符集详解
linux系统--mysql数据库默认字符集详解 - mysql的字符集配置细化到四种 对数据库server配置 对库设置 对表设置 对列设置 - 对mysql-server设置 对server设置是 ...
- 【数据库】MySQL的sql语句详解
目录 MySQL之sql语句 一, INSERT语句 insert语句的使用: 1,给表中一次性插入一条记录 2,给表中一次性插入多条记录 二, REPLACE语句 REPLACE语句的使用 1,语法 ...
- 17@MySQL数据库读现象详解(脏读、幻读、不可重复读)
文章目录 MySQL数据库读现象 一.数据库的读现象 1.脏读(dirty read):读取未提交数据 [案列详解] 2.不可重复读取 (nonrepeatable read):前后多次读取,数据内容 ...
- mysql数据库BKA算法详解
BKA算法详解 Batched Key Access理解了 MRR 性能提升的原理,我们就能理解 MySQL 在 5.6 版本后开始引入的 BatchedKey Access(BKA) 算法了.这个 ...
- MYSQL数据库使用操作详解
MySQL 客户端版 MySQL Community Server 社区版 开源免费 MySQL的官方网址: http://www.mysql.com/ ,MySQL的社区版本下载地址为: http ...
- dbeaver连接mysql 驱动jar_Jmeter(七) 从入门到精通 建立数据库测试计划实战lt;MySQL数据库gt;(详解教程)...
1.简介 在实际工作中,我们经常会听到数据库的性能和稳定性等等,这些有时候也需要测试工程师去评估和测试,上一篇文章宏哥主要介绍了jmeter连接和创建数据库测试计划的过程,宏哥在文中通过示例和代码非常 ...
- java连接mysql数据库方法_java连接mysql数据库的方法详解
连接mysql数据库在java中有几种常用的方式有官方提供的JDBC连接MySQL数据库也有后面我们讲到的其它的方式连接数据库,具体如下. JDBC连接MySQL数据库 首先要下载Connector/ ...
最新文章
- jqplot php,JSON的jqPlot
- 部署laravel项目
- 全国大学生电工数学建模竞赛赛题_A
- 交换机端口镜像(锐捷)
- 如何让Visual Studio 2010支持HTML5和CSS3
- java添加容器_如何为Java应用程序构建docker容器
- andriod studio 运行 无结果_无负压静音供水设备下篇一
- android自定义view的实现方法,Android自定义View的实现方法
- java c 转换_Java怎么转换c语言?
- python程序实现excel排序_python初学—-实现excel里面读数据进行排序(改进算法)
- 【报告分享】2021年中国新锐品牌增长潜力报告.pdf(附下载链接)
- HashMap分别按照key和value进行排序的快捷方法
- python3编译器不同版本差别大吗_python3.9的转义符使用和其他版本不一样吗?
- C语言:输入四个数a,b,c,d,将这四个数由小到大排序
- 【转】ASP.NET Web应用程序写EventLog出错的解决方案
- oracle cogs 科目,CFA一级财报科目:现金流量表详情介绍!
- 深度学习——汉字识别
- 北航超算运行matlab,北航荣获世界大学生超算总决赛一等奖!超50万亿次,又破世界纪录...
- 程序员跳槽时,如何优雅地谈薪水?
- 暗金色 rgb_杜伽TAURUS K310樱桃RGB红轴体验:做工精良、手感优秀
热门文章
- element el-table(:render-header)实现动态表头的自适应
- 微信公众号H5页面中获取openId
- linux中如何创建及复制文件/文件夹的软链接?
- python樱花_Python画一棵漂亮的樱花树(不同种樱花+玫瑰+圣诞树喔)
- 2023大数据、互联网与教育技术国际学术会议(ICBDIET 2023)
- 调用阿里云短信接口,报InvalidTimeStamp.Expired : Specified time stamp or date value is expired.错误
- 解决:无法连接Java VisualVM 插件中心, 因为Server returned HTTP response code: 503 for URL: http://www.oracle.com/
- 在线剪切板、在线拼音输入法
- IDEA设置护眼模式
- 在VMware workstation上使用win_server_2012(Hyper-v)搭建云桌面教程