mysql的count函数类型是什么意思_MySQL中的COUNT函数,你理解多少
前言:COUNT函数相比大家都不陌生,接触过数据库的兄弟们想必都用过,但是,就是这个常用的COUNT函数,却暗含许多玄机。
1、COUNT简介
看看官网对COUNT的简介
大致意思是:COUNT(expr)返回SELECT语句中expr值不为NULL的行数,返回的结果类型为BIGINT;当没有匹配的行时,返回0;SELECT(*)将返回包括NULL值的行数。
2、COUNT函数常用的几种用法
COUNT(常量),COUNT(*),COUNT(字段),那么他们之间都有什么区别。
实际上,从前面的简介中就可以看出,COUNT(字段)和COUNT(*)的区别,COUNT(字段)返回的行数是不包括该字段为NULL的字段的,而COUNT(*)返回的行数其实就是实际查询结果的总行数,那么我们再看看COUNT(常量),举个例子,例如COUNT(1),1肯定不为NULL,那么根据MySQL COUNT(expr)的简介,返回expr值不为NULL的行数,那么其实COUNT(常量)返回的也是实际查询结果的总行数。
下面我们建个表简单测试一下:
create table count_test(col1 varchar(1),col2 varchar(1));
insert into count_test value ('1','1');
insert into count_test value ('1',null);
insert into count_test value (null,'1');
insert into count_test value ('1','1');
insert into count_test value (null,'1');
insert into count_test value ('1','1');
select COUNT(1),COUNT(*),COUNT(col1),COUNT(col2) from count_test;
3、COUNT(*)和COUNT(1)到底该怎么选择
如果有看过阿里的开发手册,就会知道阿里强制要求开发人员使用COUNT(*)进行数据统计,而非是COUNT(1),到底是为什么呢?
在SQL92中,COUNT(*)是标准的统计行数的语法,而作为标准语法,MySQL本身其实是对COUNT(*)做了很多优化的,那么我们接下来看看MySQL对COUNT(*)做了哪些优化。
MySQL对COUNT(*)其实在不同的存储引擎中是不同的,那么我们主要看看两种常用的存储引擎MyISAM和InnoDB。
首先我们简单看看MyISAM和InnoDB的区别。MyISAM不支持事务,并且使用的是表锁;InnoDB支持事务,并且支持行锁。
接下来我们看看到底做了什么优化:
MyISAM:前面我们说到,MyISAM使用的是表锁,所以我们在进行读操作时,并不需要担心会有写操作对这张表进行修改,从而影响表中行数,在这样的前提下,MyISAM做了一个简单的优化,那就是单独把表中总行数单独记录下来,在使用SELECT COUNT(*)进行查询时,直接返回这个记录下来的数值就可以,当然有一个前提就是不能带where条件。
InnoDB:说完MyISAM中的优化,我们再来看看InnoDB,首先InnoDB是支持行级锁的,那么就不能像MyISAM那样将行数缓存下来,因为在进行COUNT(*)查询时是有可能有写操作对行数产生影响的。那么InnoDB到底是怎么优化COUNT(*)的呢?我们都知道,COUNT(*)实际上是要进行全表扫描的,那不可避免的就要使用索引,而COUNT(*)并不关心获取的数据各字段的字段的值,那么在使用COUNT(*)进行查询的时候,MySQL会尽量选择一个成本最小的索引进行全表扫描。那么这里就不得不说一下聚簇索引和非聚簇索引了。
在说聚簇索引和非聚簇索引之前,我们先简单的说一下,使用InnoDB存储引擎,实际上索引和数据是存在同一个文件下的(*.idb),然后表中数据是存在索引的叶子节点的(这里不理解的可以先学习一下索引和B+树),那么但有多个索引时,总不能每个索引的叶子节点都存一份完整的数据,这样不仅浪费磁盘空间,同时也为造成查询IO的瓶颈问题。这时候就有了聚簇索引和非聚簇索引。
聚簇索引:根据上面说的,不可能每一个索引的叶子结点都存一份完整的数据,只需要其中一个索引的叶子结点存一份完整的数据即可,而这个索引就是聚簇索引,默认是主键索引,如果没有主键,会找第一个非空的唯一索引,如果还是没找到,就会以rowid创建一个索引作为聚簇索引。
非聚簇索引:那么什么是非聚簇索引呢,前面说到不可能每个索引的叶子结点都存一份完整的数据,那除了聚簇索引,其他索引的叶子结点应该存什么数据呢。其实这些索引的叶子节点存的是数据id值,也就聚簇索引节点中存的key值,而这些索引就是非聚簇索引。
那么回到前面的InnoDB对COUNT(*)的优化,MySQL会尽量选择一个成本最小的索引进行全表扫描,显然扫描非聚簇索引索引的成本是远远小于扫描聚簇索引的,而MySQL会选择一个成本最小的非聚簇索引进行全表扫描,这么说来,其实创建一个非主键索引也是非常必要的。当然这些都是在查询语句不包含where、group by等的前提下。
那么,有的人会说了,难道MySQL只对COUNT(*)做了优化,对COUNT(1)没有做优化吗?我们看看MySQL官方是怎么说。
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
大意是说:对于COUNT(1)和COUNT(*),MySQL的优化是完全一样的,根本不存在谁比谁快!
那么既然COUNT(1)和COUNT(*)优化一致,而COUNT(*)又是SQL92定义的标准统计语法,那么为啥不用COUNT(*)呢?
4、总结
本文简单介绍了MySQL中COUNT(字段),COUNT(常量),COUNT(*)之间的区别,相对于COUNT(字段),COUNT(常量)和COUNT(*)的效率更高,并且查询的结果是实际的总行数(包括NULL),而COUNT(*)又是SQL92定义的标准语法,所以在日常工作中推荐使用COUNT(*)进行行统计。
不知道大家有没有发现,本文中关于MySQL对COUNT(*)的优化都有一个前提,那就是查询语句不能包括where、group by,那么在有where的条件下,MySQL又是如何对COUNT(*)进行优化的呢,这个留作一个问题,在下篇文章中进行分析。
--------------------------------------------------------------------------------------------
mysql的count函数类型是什么意思_MySQL中的COUNT函数,你理解多少相关推荐
- mysql中常用的sql函数_Mysql中的常用函数:
Mysql中的常用函数: 1.字符串函数: (1).合并字符串 concat():// concat('M','y',"SQL",'5.5');== MySQL5.5//当传入的参 ...
- mysql 过程 的函数的区别是什么意思_Mysql中存储过程和函数的区别是什么
Mysql中存储过程和函数的区别是什么 发布时间:2020-12-03 10:01:49 来源:亿速云 阅读:105 作者:小新 这篇文章主要介绍了Mysql中存储过程和函数的区别是什么,具有一定借鉴 ...
- mysql foundrows 并发_MySQL 中的 FOUND_ROWS() 函数
标签: 移植sql server 的存储过程到mysql中,遇到了sql server中的: IF @@ROWCOUNT < 1 对应到mysql中可以使用 FOUND_ROWS() 函数来替换 ...
- mysql中count出来的条数有误_Mysql中count()使用的问题?
简介: count()函数用来统计表的行数,也就是统计记录行数,很好理解的,但面试你这么说就有点单薄了. count()函数具体情况下的各种分析: 各类面试题总结了一下,应该遇到的话不会怕了: 1)为 ...
- mysql 截取括号内字符串_Mysql中字符串截取函数
MySQL中字符串的截取 substring_index(str,delim,count) 函数的使用较为普遍 函数括号里面的依次为:要分隔截取的字符串(如:"aaa_bbb_ccc&quo ...
- php mysql 时间戳查询_mysql中时间查询函数(包括时间戳)
mysql中时间查询函数(包括时间戳) 这些函数都是MySQL自带的,可以直接使用在PHP写的MySQL查询语句中哦 1-CURDATE()或CURRENT_DATE()和CURTIME()或CURR ...
- mysql空值判断函数_MySQL中的ifnull()函数判断空值
我们知道,在不同的数据库引擎中,内置函数的实现.命名都是存在差异的,如果经常切换使用这几个数据库引擎的话,很容易会将这些函数弄混淆. 比如说判断空值的函数,在Oracle中是NVL()函数.NVL2( ...
- mysql 排序开窗函数_MySQL中实现开窗函数
一.概述 row_number是数据库中常用的一个开窗函数,可以实现数据分区编号的功能,然而MySQL并不支持开窗函数.本文介绍了在MySQL中实现开窗函数的方法. 二.经典开窗函数 首先准备基础数据 ...
- mysql中的split函数_mysql中的split函数
mysql中没有字符串的分割函数,而最近在工作中,想用到这个功能,所以就在网上找了下,终于在csdn发现一个好方法.原帖的地址: 这里摘抄两个函数: DELIMITER $$ CREATE DEFIN ...
最新文章
- 翼方健数曹华:构建数据和计算互联网的必由之路
- 2020年度国家科学技术奖提名项目公示丨附全名单
- 面试题6:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList
- zookeeper与分布式系统
- java设计模式之设计原则④接口隔离原则
- SAP UI5 初学者教程之九 - 创建第一个 Component 的试读版
- linux 之 getopt_long()
- 年轻人应该买房还是租房,我给你理性分析
- vs添加icon总是变为bitmap_欧赛尔vs勒阿弗尔
- 关于类类型的隐式类型转换
- opencv python 高斯滤波_Python OpenCV实验(3):实现图像的高斯滤波处理
- unity3d 挂载脚本_Unity3D加载资源的四种方式
- 【课程作业|图论】第四章课后习题
- CentOS使用DNF配置
- 机器学习 特征选择(过滤法 封装法 嵌入法)
- istio系列:第六章-Telemetry遥测配置
- 在word或wps中使用宏代码自动生成手写体
- 计算机维护专业自我鉴定,2016届计算机系统维护专业大学生毕业自我鉴定优秀范文...
- 利用Matlab描述和求解传递函数
- maven发布jar包到私服以及从私服下载jar包的操作
热门文章
- 你问我你喜欢这个世界么
- 打开excel工作表需要密码
- C# 简易计算器功能实现
- NullPointerException:method 'android.content.BroadcastReceiver.onReceive' on a null object reference
- chrome不走proxifier
- (0x80040154): 没有注册类别 (异常
- stm32固件库--滴答定时器
- 股海沉浮:2005年到2007年超级大牛市行情领涨板块分析,推及2009年可能的走势
- python 主语,python自然语言处理学习笔记(五)—— 词性标注
- 【win32】day11-windows的库/静态库/动态库