关于数据库中行数统计,无论是MySQL还是Oracle,都有一个函数可以使用,那就是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函数了。

1.初识COUNT

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

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

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

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

2.COUNT(字段)、COUNT(常量)和COUNT(*)之间的区别

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

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

COUNT(*)是SQL92定义的标准统计行数的语法,因为是标准语法,所以MySQL数据库进行过很多优化。

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

3.COUNT(*)的优化

MySQL主要使用2种执行引擎:

  • InnoDB引擎
  • MyISAM引擎

MyISAM不支持事务,MyISAM中的锁是表级锁;而InnoDB支持事务,并且支持行级锁。

MyISAM

MyISAM做了一个简单的优化,把表的总行数单独记录下来,如果执行count(*)时可以直接返回,前提是不能有where条件。MyISAM是表级锁,不会有并发的行操作,所以查到的结果是准确的。

InnoDB

InnoDB不能使用这种缓存操作,因为支持事务,大部分操作都是行级锁,行可能被并行修改,那么缓存记录不准确。

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

通过低成本的索引进行扫表,而不关注表的具体内容。

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

MySQL会优先选择最小的非聚簇索引来扫表。

优化的前提是查询语句中不包含where条件和group by条件。

4.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(*),因为这是SQL92定义的标准统计行数的语法。

5.COUNT(字段)

进行全表扫描,判断指定字段的值是否为NULL,不为NULL则累加。

性能比count(1)count(*)慢。

6.总结

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

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

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

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

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

MySQL学习笔记:count(1)、count(*)、count(字段)的区别的更多相关文章

  1. MySQL学习笔记(三)——计算字段及常用函数

    拼接字段-Concat()函数        将值连接在一起构成单个值.注意:大多数DBMS使用+或者||来实现拼接,mysql则使用Concat()函数来实现. 去空格函数-Trim函数       ...

  2. 数据库MySQL学习笔记高级篇

    数据库MySQL学习笔记高级篇 写在前面 学习链接:数据库 MySQL 视频教程全集 1. mysql的架构介绍 mysql简介 概述 高级Mysql 完整的mysql优化需要很深的功底,大公司甚至有 ...

  3. 一千行MySQL学习笔记 (转)

    出处:  一千行MySQL学习笔记 /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权 ...

  4. MySql学习笔记(一)之DQL常用查询

    MySql学习笔记(一)之DQL常用查询 前言:mysql是中小型的数据库软件,SQL语言分为DDL,DCL,DML,DQL四种,在这里重点讲解DQL的单表查询. 正文:在学习mysql单表查询之前, ...

  5. mysql basic operation,mysql总结,对mysql经常使用语句的详细总结,MySQL学习笔记

    mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ; 1.显示数据库列表.show d ...

  6. MySQL学习笔记-锁相关话题

    在事务相关话题中,已经提到事务隔离性依靠锁机制实现的.在本篇中围绕着InnoDB与MyISAM锁机制的不同展开,进而描述锁的实现方式,多种锁的概念,以及死锁产生的原因.   Mysql常用存储引擎的锁 ...

  7. Mysql学习笔记(三)对表数据的增删改查。

    正文内容. 这一部分是最简单的,也是最麻烦的.简单是因为其实只包括增删该插四个部分.大体上看,增加数据.删除数据.修改数据.查询数据都不麻烦啊,我们日常都是常用的.这个谁不会呢?以前在培训机构学mys ...

  8. MySQL学习笔记一

    MySQL 学习笔记 一 一.数据库简单介绍 1. 按照数据库的发展时间顺序,主要出现了以下类型数据库系统: Ø 网状型数据库 Ø 层次型数据库 Ø 关系型数据库 Ø 面向对象数据库 上面4中数据库系 ...

  9. Mysql学习笔记(一)数据类型

    原文:Mysql学习笔记(一)数据类型 学习内容: Mysql基本数据类型. 1.数字类型.. i.整型     Mysql数据类型             含义(有符号)     tinyint(m ...

  10. MySQL学习笔记-cache 与 buffer

    Cache和Buffer是两个不同的概念,简单的说,Cache是加速"读",而 buffer是缓冲"写",前者解决读的问题,保存从磁盘上读出的数据,后者是解决写 ...

随机推荐

  1. linux下如何查看当前内核的配置?

    答: zcat /proc/config.gz 当然有个前提条件,需要打开内核的以下两个选项(CONFIG_IKCONFIG和CONFIG_IKCONFIG_PROC): General setup ...

  2. Ubuntu16.04中VirtualBox中安装FreeBSD

    获取镜像 FreeBSD官网:https://www.freebsd.org,打开后即可看到“Download Freebsd”的按钮,点击进去 进入版本选择的页面.可以看到当前RELEASR版本,旧 ...

  3. 转 CentOS 7 环境下安装Maven

    下载安装文件 wget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3 ...

  4. GBK格式字符串右补空格

    public class Test2 {   public static void main(String[] s) throws IOException {   List<User> l ...

  5. Redis安装与配置( Windows10 )

    本文链接:https://blog.csdn.net/gaokcl/article/details/82814134linux安装参考:https://blog.csdn.net/gaokcl/art ...

  6. 前台请求响应json

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  7. AP注册

    1.ac发现ap 两种模式:二层发现.三层发现 按ap与ac所处ip网段不同,可以把注册过程分为二层模式和三层模式: 两种模式均通过发送discovery报文进行,二层模式discovery报文仅在同 ...

  8. Vue.js 使用 $refs 定位 DOM 出现 undefined

    找到这篇文章,写得不错,记录一下.https://www.jianshu.com/p/090937a480b5

  9. freeRTOS学习一

    freeRTOS中的链表结构: /* * Definition of the only type of object that a list can contain. 链表中的节点 */ struct ...

  10. readline安装

    wget -c ftp://ftp.gnu.org/gnu/readline/readline-6.2.tar.gz tar -zxvf readline-6.2.tar.gz cd readline ...