sqlserver建表语句_重新认识MySQL中的COUNT语句

在数据库的增删改查操作中,使用最频繁的就是查询操作。

而在所有查询操作中,统计数量操作更是经常被用到。

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

而对于COUNT,有几个问题很值得去思考:

1、COUNT有几种用法?

2、COUNT(字段名)和COUNT()的查询结果有什么不同?

3、COUNT(1)和COUNT()之间有什么不同?

4、COUNT(1)和COUNT()之间的效率哪个更高?

5、为什么《阿里巴巴Java开发手册》建议使用COUNT()

6、MySQL的MyISAM引擎对COUNT()做了哪些优化?

7、MySQL的InnoDB引擎对COUNT()做了哪些优化?

8、上面提到的MySQL对COUNT()做的优化,有一个关键的前提是什么?

9、SELECT COUNT() 的时候,加不加where条件有差别吗?

10、COUNT()、COUNT(1)和COUNT(字段名)的执行过程是怎样的?

如果以上10道题,全部准确无误的回答的话,那说明你真的很了解COUNT函数了,如果有哪些知识点是不了解的,那么本文正好可以重新帮你认识一下Count,也为数据库优化做一些思考。

认识COUNT

关于COUNT函数的介绍:

1、COUNT(expr) ,返回SELECT语句检索的行中expr的值不为NULL的数量。结果是一个BIGINT值。

2、如果查询结果没有命中任何记录,则返回0

3、但是,值得注意的是,COUNT() 的统计结果中,会包含值为NULL的行数。

例:

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

除了COUNT(id)和COUNT()以外,还可以使用COUNT(常量)(如COUNT(1))来统计行数,那么这三条SQL语句有什么区别呢?

到底哪种效率更高呢?

为什么《阿里巴巴Java开发手册》中强制要求不让使用 COUNT(列名)或 COUNT(常量)来替代COUNT()呢?

09a7f121c995383b506cef851cae6e79.png

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

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

那么列名、 常量 和 这三个条件中,常量是一个固定值,肯定不为NULL。

可以理解为查询整行,所以肯定也不为NULL,那么就只有列名的查询结果有可能是NULL了。

所以, COUNT(常量) 和 COUNT()表示的是直接查询符合条件的数据库表的行数。

而COUNT(列名)表示的是查询符合条件的列的值不为NULL的行数。

除了查询得到结果集有区别之外,COUNT()相比COUNT(常量) 和 COUNT(列名)来讲,COUNT()是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 tblname语句,确实在扫表的过程中做了一些优化。

前提是查询语句中不包含WHERE或GROUP BY等条件。

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

我们知道,InnoDB中索引分为聚簇索引(主键索引)和非聚簇索引(非主键索引),聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值。

所以,相比之下,非聚簇索引要比聚簇索引小很多,所以MySQL会优先选择最小的非聚簇索引来扫表。

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

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

COUNT()和COUNT(1)

介绍完了COUNT(),接下来看看COUNT(1),对于,这二者到底有没有区别,网上的说法众说纷纭。

有的说COUNT()执行时会转换成COUNT(1),所以COUNT(1)少了转换步骤,所以更快。

还有的说,因为MySQL针对COUNT()做了特殊优化,所以COUNT()更快。

那么,到底哪种说法是对的呢?

看下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定义的标准统计行数的语法,而且本文只是基于MySQL做了分析,关于Oracle中的这个问题,也是众说纷纭的呢。

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.mzph.cn/news/288628.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

显示学生各科成绩和总成绩-面试被问到

表结构如下: name schedule score 张三 语文 20张三 数学 60张三 英语 80李四 数学 30李四 英语 60李四 语文 80 想要的结果如下: 姓名 语文 数学 英语 总成绩 …

sql INNER JOIN 取得两个表中存在连接匹配关系的记录(mysql)

首先:JOIN 通常与 ON 关键字搭配使用 其次我们来看我们的两个表格: table1: table2: 在这里,INNER JOIN(内连接,或等值连接):取得两个表中存在连接匹配关系的记录。 例如我要取到table1和table2之…

【Linux】IPC-消息队列

问题 消息队列id 和键值KEY区别? 首先要注意一个概念:IPC结构都是内核的结构。也就是说IPC结构由内核维护,对于每个进程都是公共的,不属于某个特定进程。只有这样,IPC结构才能支持它们“进程间通信”的功能。 有两个东…

linux shell之得到当前路径下的目录

方法1 find . -type d 方法2 ^是开头开头得意思,然后d是dictionary意思 ls -al | grep ^d 方法3 ls -F | grep /$ 方法4 ls -d */

python中html.parser_在Python中使用HTMLParser解析HTML的教程

如果我们要编写一个搜索引擎,第一步是用爬虫把目标网站的页面抓下来,第二步就是解析该HTML页面,看看里面的内容到底是新闻、图片还是视频。假设第一步已经完成了,第二步应该如何解析HTML呢?HTML本质上是XML的子集&…

分别统计出其中英文字母、空格、数字和其它字符的个数 matlab 程序,编写一段程序,要求先输入一行字符,然后分别统计出其中英文...

编写一个求和的程序,要求能任意输入两个整数,求和 用javascript写functionadd(){varAdocument.getElementById("a").value;varBdocument.getElementById("b").value;varA用C语言编写一段程序,输入一行字符,分别统计出其中的英文字母、空格、数字和其他字符…

【ArcGIS遇上Python】长时间序列(30年)每两组栅格数据对应做减法运算求物候参数

Python语言在ArcGIS软件中发挥着乾坤大挪移的作用,然而很多人并不知道它的厉害之处。今天我们利用Python语言来批处理遥感物候数据,获取物候期的参数。 说明: (1)Up_Path:始期数据路径变量 (2)Down_Path:末期数据路径变量 (3)outPath:相减输出结果路径变量 完…

Blazor University (14)渲染树

原文链接:https://blazor-university.com/components/render-trees/渲染树当浏览器呈现内容时,它不仅绘制 HTML 中定义的元素,还必须根据页面大小(元素流)计算绘制它们的位置。例如,以下 Bootstrap HTML 将…

思科加强生成树性能的属性(Portfast /Uplinkfast/BackboneFast)与RSTP的关系

思科加强生成树性能的属性(Portfast/Uplinkfast/BackboneFast)与RSTP的关系本文截自于博主CCNP交换技术稿件内容4.2.6思科加强生成树性能的属性(Portfast/Uplinkfast/BackboneFast)与RSTP的关系首先说明一下,为什么笔者…

数据结构(java语言描述)顺序栈的使用

1.声明Istack接口; package stack;public interface Istack { public void clear(); public boolean isEmpty(); public int length(); public Object peek(); public void push(Object x) throws Exception; public Objec…

sql LEFT JOIN RIGHT JOIN(左连接)(mysql)

我们首先来看我们的两个表: table1: table2: 在这里,LEFT JOIN(内连接,或等值连接):取得左表(table1)完全记录,即是右表(table2)并无对应匹配记录。 …

linux shell之xargs 、tr、sha1sum、head、tail一般使用

1 xargs命令 有点类似-exec命令 1)删除当前目录下面的c文件 find . -name "*.c" | xargs rm 2)统计当前c文件里面的代码行数 find . -name "*.c" | xargs wc -l 2 tr命令 替换命令 1)把大小替换成小写 echo &quo…

php的_auto,AutoPHPCheck下载

AutoPHPCheck官方版是一款相当优秀的php开发人员专用PHP验证工具,AutoPHPCheck官方版功能全面,便捷好用,支持执行快速验证来帮助您确保代码的安全性,并且软件还附带了一个基本的语法检查器,可以查找并帮助您处理错误。…

python0表示剪刀_石头,纸,剪刀Python代码。帮助简化

我是Python新手,只写过几个程序。这是我最近为一个“石头剪子”游戏编写的代码。我已经测试过了,效果很好。有什么方法可以简化它吗?谢谢!import randomwins0losses0ties0rounds0r1 #rockp2 #papers3 #scissorsy "The compu…

Google图片加载库Glide的简单封装GlideUtils

Google图片加载库Glide的简单封装GlideUtils

【ArcGIS遇上Python】Python实现点转栅格(PointToRaster)

在ArcGIS中提供了点转栅格(PointToRaster)的工具,如下所示: 参数说明: (1)file:点图层(.shp) (2)data:值字段 (3)outFile:转换后的栅格图层 (4)9660.848118:空间分辨率 python批处理代码: import arcpy arcpy.gp.overwriteOutput=1 arcpy.env.workspace=&…

ASP.NET Core认证授权方案

前言在前面我讲过基于token的权限认证,然后前几天有小伙伴私信我,怎么做一个身份认证也就是授权。在Asp.net Core常见的授权方式有:基于角色的授权,有基于声明的授权,有基于策略的授权, 这三种授权我就不做过多介绍了,…

linux基础知识个人总结

linux基础知识个人总结第一章:1. Linux发展史略,有代表性的Linux发行版:Suse、slackware、ubuntu、RedHat、CentOS2. GNU是Richard Stallman在1983年发起的一项自由软件运动,目标是为了创建一套完全自由的操作系统,它要…

linux shell之pushd、popd、dirs

1 问题 我们有时候需要保存多个路径,上下键切换不方便,用cd-只能到上个目录,我们可以用dirs和pushd和popd 2 dirs、pushd、popd dirs: 这个命令显示栈里面所有的路径,一定会包含当前路径,常用参数如下 dirs -v 显示栈里面的所有…

插入排序—直接插入排序(Straight Insertion Sort)

基本思想: 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插插入到已入,直至整个序列有序为止。 要点:设…