MySQL的COUNT语句,竟然都能被面试官虐的这么惨!?

关于数据库中行数统计,无论是MySQL还是Oracle,都有一个函数可以使用,那就是COUNT

但是,就是这个常用的COUNT函数,却暗藏着很多玄机,尤其是在面试的时候,一不小心就会被虐。不信的话请尝试回答下以下问题:


以上10道题,如果您可以全部准确无误的回答的话,那说明你真的很了解COUNT函数了,如果有哪些知识点是不了解的,那么本文正好可以帮你答疑解惑。


1、认识COUNT

关于COUNT函数,在MySQL官网中有详细介绍:

  1. COUNT(expr) ,返回SELECT语句检索的行中expr的值不为NULL的数量。结果是一个BIGINT值。
  2. 如果查询结果没有命中任何记录,则返回0
  3. 值得注意的是,COUNT(*) 的统计结果中,会包含值为NULL的行数。

即以下表记录

create table #bla(id int,id2 int)
insert #bla values(null,null)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,null)

使用语句count(*),count(id),count(id2)查询结果如下:

select count(*),count(id),count(id2)
from #bla

results 7 3 2

除了COUNT(id)COUNT(*)以外,还可使用COUNT(常量)(如COUNT(1))来统计行数,那么这三条SQL语句有什么区别呢?到底哪种效率更高呢?为什么《阿里巴巴Java开发手册》中强制要求不让使用 COUNT(列名)或 COUNT(常量)来替代 COUNT(*)呢?


COUNT(列名)、COUNT(常量)和COUNT(*)之间的区别

前面提到过COUNT(expr)用于做行数统计,那么COUNT(列名)、 COUNT(常量) 和 COUNT(*)这三种语法中,expr分别指的是列名、 常量 和 *。

这三个条件中,常量是一个固定值,肯定不为NULL。*可以理解为查询整行,所以肯定也不为NULL,那么就只有列名的查询结果有可能是NULL。

所以, COUNT(常量) 和 COUNT(*)表示的是直接查询符合条件的数据库表的行数。而COUNT(列名)表示的是查询符合条件的列的值不为NULL的行数。

除了查询得到结果集有区别之外,COUNT(*)相比COUNT(常量) 和 COUNT(列名)来讲,OUNT(*)是SQL92定义的标准统计行数的语法,因为他是标准语法,所以MySQL数据库对他进行过很多优化。

SQL92,是数据库的一个ANSI/ISO标准。它定义了一种语言(SQL)以及数据库的行为(事务、隔离级别等)。


COUNT(*)的优化

前面提到了COUNT(*)是SQL92定义的标准统计行数的语法,所以MySQL数据库对他进行过很多优化。那么,具体都做过哪些事情呢?

这里的介绍要区分不同的执行引擎。MySQL中比较常用的执行引擎就是InnoDB和MyISAM。 MyISAM和InnoDB有很多区别,其中有一个关键的区别和我们接下来要介绍的COUNT(*)有关,那就是MyISAM不支持事务,MyISAM中的锁是表级锁;而InnoDB支持事务,并且支持行级锁。

因为MyISAM的锁是表级锁,所以同一张表上面的操作需要串行进行,所以,MyISAM做了一个简单的优化,那就是它可以把表的总行数单独记录下来,如果从一张表中使用COUNT(*)进行查询的时候,可以直接返回这个记录下来的数值就可以了,当然,前提是不能有where条件。

MyISAM之所以可以把表中的总行数记录下来供COUNT(*)查询使用,那是因为MyISAM数据库是表级锁,不会有并发的数据库行数修改,所以查询得到的行数是准确的。

但是,对于InnoDB来说,就不能做这种缓存操作了,因为InnoDB支持事务,其中大部分操作都是行级锁,所以可能表的行数可能会被并发修改,那么缓存记录下来的总行数就不准确了。

但是,InnoDB还是针对COUNT(*)语句做了些优化的。

在InnoDB中,使用COUNT(*)查询行数的时候,不可避免的要进行扫表了,那么,就可以在扫表过程中下功夫来优化效率了。

从MySQL 8.0.13开始,针对InnoDB的SELECT COUNT(*) FROM tbl_name语句,确实在扫表的过程中做了一些优化。前提是查询语句中不包含WHERE或GROUP BY等条件。

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

我们知道,InnoDB中索引分为聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值。 所以,相比之下,非聚簇索引要比聚簇索引小很多,所以MySQL会优先选择最小的非聚簇索引来扫表。

所以,当我们建表的时候,除了主键索引以外,创建一个非主键索引还是有必要的。

至此,我们介绍完了MySQL数据库对于COUNT(*)的优化,这些优化的前提都是查询语句中不包含WHERE以及GROUP BY条件


COUNT(*)和COUNT(1)

介绍完COUNT(*),接下来看看COUNT(1),对于,这二者到底有没有区别,网上的说法众说纷纭。看下MySQL官方文档是怎么说的:

InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.

画重点:same way , no performance difference。

所以,对于COUNT(1)和COUNT(*),MySQL的优化是完全一样的,根本不存在谁比谁快! 那既然COUNT(*)和COUNT(1)一样,建议用哪个呢? 建议使用COUNT(*)!因为这个是SQL92定义的标准统计行数的语法。


COUNT(字段)

最后,就是一直还没提到的COUNT(字段),他的查询就比较简单粗暴,就是进行全表扫描,然后判断指定字段的值是不是为NULL,不为NULL则累加。相比COUNT(*),COUNT(字段)多了一个步骤就是判断所查询的字段是否为NULL,所以他的性能要比COUNT(*)慢。


总结

本文介绍了COUNT函数的用法,主要用于统计表行数。主要用法有COUNT(*)COUNT(字段)COUNT(1)

因为COUNT(*)是SQL92定义的标准统计行数的语法,所以MySQL对他进行了很多优化,MyISAM中会直接把表的总行数单独记录下来供COUNT(*)查询,而InnoDB则会在扫表的时候选择最小的索引来降低成本。当然,这些优化的前提都是没有进行where和group的条件查询。

在InnoDB中COUNT(*)COUNT(1)实现上没有区别,且效率一样,但COUNT(字段)需要进行字段的非NULL判断,所以效率会低一些。

因为COUNT(*)是SQL92定义的标准统计行数的语法,并且效率高,所以请直接使用COUNT(*)查询表的行数!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/2786.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一文了解Jackson注解@JsonFormat及失效解决

背景 项目中使用WRITE_DATES_AS_TIMESTAMPS: true转换日期格式为时间戳未生效。如下: spring:jackson:time-zone: Asia/Shanghaiserialization:WRITE_DATES_AS_TIMESTAMPS: true尝试是否关于时间的注解是否会生效,使用JsonForma和JsonFiled均失效。 常…

【Docker】CAdvisor+InfluxDB+Granfana容器监控

文章目录原生命令 docker stats容器监控3剑客CIGCAdvisorInfluxDBGranfanacompose容器编排,一套带走新建目录新建3件套组合的 docker-compose.yml检查配置,有问题才有输出 docker-compose config -q启动docker-compose文件 docker-compose up -d测试浏览…

HTML5 Canvas

HTML5 Canvas <canvas>元素是HTML5中的新元素&#xff0c;通过使用该元素&#xff0c;你可以在网页中绘制所需的图形。 标签定义图形&#xff0c;比如图表和其他图像&#xff0c;您必须使用脚本来绘制图形。在画布上&#xff08;Canvas&#xff09;画一个红色矩形&#…

Java基础知识之HashMap的使用

一、HashMap介绍 HashMap是Map接口的一个实现类&#xff08;HashMap实现了Map的接口&#xff09;&#xff0c;它具有Map的特点。HashMap的底层是哈希表结构。 Map是用于保存具有映射关系的数据集合&#xff0c;它具有双列存储的特点&#xff0c;即一次必须添加两个元素&#xf…

5个高清/4K视频素材网站,免费下载。

本期跟大家分享5个超好用的视频素材网站&#xff0c;4K质量&#xff0c;免费可商用。 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库主要提供设计素材为主&#xff0c;自媒体相关素材也很多&#xff0c;像商用图片、背景图、视频素材、音频素材都很齐…

算法刷题总结 (二) 回溯与深广搜算法

算法总结2 回溯与深广搜算法一、理解回溯算法1.1、回溯的概念1.2、回溯法的效率1.3、回溯法问题分类1.4、回溯法的做题步骤二、经典问题2.1、组合问题2.1.1、77. 组合 - 值不重复2.1.2、216.组合总和III - 值不重复且等于目标值2.1.3、17. 电话号码的字母组合 - 双层回溯2.1.4、…

KafKa知识汇总

前言 汇总相关知识 Kafka快速实战与基本原理详解

LeetCode:215. 数组中的第K个最大元素

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340;算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;215. 数组中的第K个最大元素 题目描述&#xff1a;给定整数数组nums和整…

Django 之 Cookie 和 Session

3. Cookie 和 Session 会话 因为 HTTP 协议是无状态的&#xff0c;每次浏览器请求 request都是无状态的&#xff0c;后台服务器无法识别当前请求与上一次请求及之后请求是否为同一用户。 对于静态网站来说无所谓&#xff08;所有用户看到的都是一样的&#xff09;&#xff0c…

【C++】引用详细解析

目录引用的概念引用的用法引用的特性常引用&#xff08;涉及权限的放大与缩小&#xff09;引用的使用场景**作参数****作返回值**正确使用引用返回传值、传引用效率比较引用和指针的区别引用的概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0…

干货 | 开关电源的PCB布线设计技巧—如何降低EMI?

开关电源PCB排版是开发电源产品中的一个重要过程。许多情况下&#xff0c;一个在纸上设计得非常完美的电源可能在初次调试时无法正常工作&#xff0c;原因是该电源的PCB排版存在着许多问题。为了适应电子产品飞快的更新换代节奏&#xff0c;产品设计工程师更倾向于选择在市场上…

【Zblog建站】搭建属于自己的博客网站,并内网穿透实现公网访问

文章目录1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置4. 公网访问测试5. 结语1. 前言 想要成为一个合格的技术宅或程序员&#xff0c;自己搭建网站制作网页是绕不开…

第十四届蓝桥杯三月真题刷题训练——第 20 天

目录 第 1 题&#xff1a;纸张尺寸 问题描述 输入格式 输出格式 样例输入1 样例输出1 样例输入 2 样例输出 2 运行限制 代码&#xff1a; 解析&#xff1a; 第 2 题&#xff1a;最大数字 第 3 题&#xff1a;全排列的价值_递推公式 问题描述 输入格式 输出格式…

【中级软件设计师】—操作系统考点总结篇(二)

【中级软件设计师】—操作系统考点总结篇&#xff08;二&#xff09; 1.操作系统概述 1.1操作系统的功能 1.2 特殊的操作系统 1.3 进程的概念和状态 进程与程序的区别&#xff1a; 进程是程序的一次执行过程&#xff0c;没有程序就没有进程 程序是一个静态的概念&#xff0c;…

flowable-ui

一、介绍 flowable-ui主要用于画流程图,之后再使用flowable整合Spring Boot。Flowable提供了一个web UI应用程序来演示和利用Flowable项目提供的功能。 flowable-ui的官网文档地址为: https://www.flowable.com/open-source/docs/bpmn/ch14-Applications/ 二、安装flowab…

Counterpoint发布颈戴式耳机市场报告,苹果Find My加持不易丢

根据市场调查机构 Counterpoint 公布的 2022 年第 4 季度报告&#xff0c;一加凭借着 20.2% 的市场占有率&#xff0c;成为印度市场最大的颈戴式耳机市场厂商。 一加以 20.2% 的市场占有率领先&#xff0c;boAt 以 16% 的份额位居第二。一加云耳 Z2 已经连续 3 个季度成为印度…

【CodeForces】Codeforces Round 859 (Div. 4) D

嘿嘿嘿&#xff0c;CF虐我千百遍&#xff0c;我待CF如初见&#xff01; &#xff08;doge&#xff09; 目录 题目含义&#xff1a; 前缀和&#xff1a; 代码 &#x1f386;音乐分享&#xff08;点击链接可以听哦&#xff09; A Hundred Miles&#xff08;一百英里&#xff09;…

JDBC——Java数据库连接

文章目录一、数据库工具类二、JDBC—— Java数据库连接三、执行DML语句四、执行DQL语句五、关联查询六、执行预编译SQL语句七、SELECT语句八、练习创建表:student1九、向student1表中插入100条数据十、删除名字为Test20---Test100的学生十一、将student1表中所有test学生的年龄…

基于深度学习的花卉检测与识别系统(YOLOv5清新界面版,Python代码)

摘要&#xff1a;基于深度学习的花卉检测与识别系统用于常见花卉识别计数&#xff0c;智能检测花卉种类并记录和保存结果&#xff0c;对各种花卉检测结果可视化&#xff0c;更加方便准确辨认花卉。本文详细介绍花卉检测与识别系统&#xff0c;在介绍算法原理的同时&#xff0c;…

在不丢失数据的情况下解锁锁定的 Android 手机的 4 种方法

尽管您可以使用指纹解锁手机&#xff0c;但大多数智能手机都需要 PIN 码、图案或字母数字代码作为主密码。如果您有一段时间没有输入手机密码&#xff0c;很容易忘记。正是由于这个原因&#xff0c;即使您打开了指纹解锁&#xff0c;大多数智能手机也会让您每天至少输入一次 PI…