前言: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函数,你理解多少相关推荐

  1. mysql中常用的sql函数_Mysql中的常用函数:

    Mysql中的常用函数: 1.字符串函数: (1).合并字符串 concat():// concat('M','y',"SQL",'5.5');== MySQL5.5//当传入的参 ...

  2. mysql 过程 的函数的区别是什么意思_Mysql中存储过程和函数的区别是什么

    Mysql中存储过程和函数的区别是什么 发布时间:2020-12-03 10:01:49 来源:亿速云 阅读:105 作者:小新 这篇文章主要介绍了Mysql中存储过程和函数的区别是什么,具有一定借鉴 ...

  3. mysql foundrows 并发_MySQL 中的 FOUND_ROWS() 函数

    标签: 移植sql server 的存储过程到mysql中,遇到了sql server中的: IF @@ROWCOUNT < 1 对应到mysql中可以使用 FOUND_ROWS() 函数来替换 ...

  4. mysql中count出来的条数有误_Mysql中count()使用的问题?

    简介: count()函数用来统计表的行数,也就是统计记录行数,很好理解的,但面试你这么说就有点单薄了. count()函数具体情况下的各种分析: 各类面试题总结了一下,应该遇到的话不会怕了: 1)为 ...

  5. mysql 截取括号内字符串_Mysql中字符串截取函数

    MySQL中字符串的截取 substring_index(str,delim,count) 函数的使用较为普遍 函数括号里面的依次为:要分隔截取的字符串(如:"aaa_bbb_ccc&quo ...

  6. php mysql 时间戳查询_mysql中时间查询函数(包括时间戳)

    mysql中时间查询函数(包括时间戳) 这些函数都是MySQL自带的,可以直接使用在PHP写的MySQL查询语句中哦 1-CURDATE()或CURRENT_DATE()和CURTIME()或CURR ...

  7. mysql空值判断函数_MySQL中的ifnull()函数判断空值

    我们知道,在不同的数据库引擎中,内置函数的实现.命名都是存在差异的,如果经常切换使用这几个数据库引擎的话,很容易会将这些函数弄混淆. 比如说判断空值的函数,在Oracle中是NVL()函数.NVL2( ...

  8. mysql 排序开窗函数_MySQL中实现开窗函数

    一.概述 row_number是数据库中常用的一个开窗函数,可以实现数据分区编号的功能,然而MySQL并不支持开窗函数.本文介绍了在MySQL中实现开窗函数的方法. 二.经典开窗函数 首先准备基础数据 ...

  9. mysql中的split函数_mysql中的split函数

    mysql中没有字符串的分割函数,而最近在工作中,想用到这个功能,所以就在网上找了下,终于在csdn发现一个好方法.原帖的地址: 这里摘抄两个函数: DELIMITER $$ CREATE DEFIN ...

最新文章

  1. 翼方健数曹华:构建数据和计算互联网的必由之路
  2. 2020年度国家科学技术奖提名项目公示丨附全名单
  3. 面试题6:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList
  4. zookeeper与分布式系统
  5. java设计模式之设计原则④接口隔离原则
  6. SAP UI5 初学者教程之九 - 创建第一个 Component 的试读版
  7. linux 之 getopt_long()
  8. 年轻人应该买房还是租房,我给你理性分析
  9. vs添加icon总是变为bitmap_欧赛尔vs勒阿弗尔
  10. 关于类类型的隐式类型转换
  11. opencv python 高斯滤波_Python OpenCV实验(3):实现图像的高斯滤波处理
  12. unity3d 挂载脚本_Unity3D加载资源的四种方式
  13. 【课程作业|图论】第四章课后习题
  14. CentOS使用DNF配置
  15. 机器学习 特征选择(过滤法 封装法 嵌入法)
  16. istio系列:第六章-Telemetry遥测配置
  17. 在word或wps中使用宏代码自动生成手写体
  18. 计算机维护专业自我鉴定,2016届计算机系统维护专业大学生毕业自我鉴定优秀范文...
  19. 利用Matlab描述和求解传递函数
  20. maven发布jar包到私服以及从私服下载jar包的操作

热门文章

  1. 你问我你喜欢这个世界么
  2. 打开excel工作表需要密码
  3. C# 简易计算器功能实现
  4. NullPointerException:method 'android.content.BroadcastReceiver.onReceive' on a null object reference
  5. chrome不走proxifier
  6. (0x80040154): 没有注册类别 (异常
  7. stm32固件库--滴答定时器
  8. 股海沉浮:2005年到2007年超级大牛市行情领涨板块分析,推及2009年可能的走势
  9. python 主语,python自然语言处理学习笔记(五)—— 词性标注
  10. 【win32】day11-windows的库/静态库/动态库