mysql中使用count()统计总结与思考

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 如果你的需要是统计总行数时,为什么要使用count(*),而避免使用指定具体的列名?count()函数里面的参数是列名的的时候,那么会计算这个字段有值项的次数。也就是,该字段没有值的项并不会进入计算范围(就是网上常说的值为null的项不纳入统计) 很多地方都有类似表述: COUNT ( column ) counts all non-NULL occurences (or should …  计算所有column字段为"非null"值的总数。


如果你的需要是统计总行数时,为什么要使用count(*),而避免使用指定具体的列名?

count()函数里面的参数是列名的的时候,那么会计算这个字段有值项的次数。也就是,该字段没有值的项并不会进入计算范围(就是网上常说的值为null的项不纳入统计)

很多地方都有类似表述:

COUNT ( column ) counts all non-NULL occurences (or should ;) …  计算所有column字段为"非null"值的总数。

COUNT ( * ) counts all rows.


这样的话,你想统计的行数并不准确。更重要的是,还会增加消耗。因为,需要判断扫描所有行才知道值是否有值。

一般是建议以count(字段名)替代count(*)。实际使用中,我的理解是,你要统计那个列的总数,比如我想统计会员的总数,那么我可以以uid作为参考,uid是null的都不去扫描了

于是查询就是select count(uid) from members



如果使用count(*),它会计算总行数。不管你字段是否有值都会列入计算范围。

另外一点:myisam引擎很容易获得总行数的统计。查询速度变得更快。因为myisam存储引擎已经存储了表的总行数。

应该是每次新增加一行,这个计数器就加1。英文资料是这样子说的:

 On MyISAM, doing a query that does SELECT COUNT(*) FROM {some_table}, is very fast, since MyISAM keeps the information in the index

也就是说,把表的总数缓存在索引中了。

 

注意一点:myisam存储引擎的表,count(*)速度快的也仅仅是不带where条件的count。这个想想容易理解的,因为你带了where限制条件,原来所以中缓存的表总数能够直接返回用吗?不能用。这个查询引擎也是需要根据where条件去表中扫描数据,进行统计返回的。



归纳:实际编程中统计总行数是经常用到的。此时使用count(*)多处可见。我很少看到有人使用列名作为参数:count(a)的情况。即使是这样使用,可能其初衷也是想统计行数。只是不知道这样所造成的细微差异而错误使用了"列名"的形式。

 

针对Innodb表,尽量不执行 SELECT COUNT(*) 语句,因为Innodb表没有类似MyISAM那样的内部计数器来记录表记录总量,执行这个操作将会全表扫描,速度很慢。所以呢,表的行数越多,扫描的时间就越多。当你表行数还是小数量的时候体会不出速度差距。比如百万也感觉不出明显。上千万就会很明显速度差别了。

对策:对innob存储引擎的大表进行select count()统计总数操作,业界都会尽量避免。

如果要查询innodb存储引擎的表总数,要怎么办?

总结两种方案:

方案一:通过查询information_schema库,它记录了innodb类型每个表大致的数据行数

 

方案二(更优):涉及到总数操作,专门维护一个总数。新注册一个会员,总数值加1,需要总数的时候直接拿这个总数,比如分页时。

方案二的扩展性更好,随着会员表数量增大,水平切分会员表,要获取用户总数。可以专门看这张表。

 

在网上看到有人问自己的innodb存储引擎的表数据行数到10亿了,要进行分页,count(*)操作很慢怎么解决。

其实像对大数据量进行统计总数的操作,并不是要求非常精准的总数,没好多人关心差几个。像网易,凤凰网这些新闻有很多人评论,这个评论总数,如果每次点击分页的时候都进行一次count操作,那速度肯定不会快到哪里去。他们一般也是采用计数器的办法。每次新增加一条评论,就把值加1。这样分页的时候直接拿这个总数进行分页。

总数可能是存在内存中,这样分页计算的时候速度很快。累加操作的时候将内存中的值加1。总数这个值要持久化,还是要存到磁盘上的,也就是数据库中(可以是关系型数据库,也可以是mongdb这样的数据库很适合存储计数)。把总数放在内存中,只是避免频繁的磁盘i/0操作(操作数据库就要涉及到磁盘读写)。

 

ps:这种计数器的思想在计算机的很多地方都会用到。比如mysql数据库他自己的information_schema库维护每个表的row总数,就是这样的方式。

 

我有个疑问:针对innodb存储引擎,使用count(1)替代count(*)就避免全表扫描,速度很快吗?

orcalce数据库有专门对count(1)和count(*)的区别。

count(1)其实这个1,并不是表示第一个字段,而是表示一个固定值。

count(1),其实就是计算一共有多少符合条件的行。
1并不是表示第一个字段,而是表示一个固定值。
其实就可以想成表中有这么一个字段,这个字段就是固定值1,count(1),就是计算一共有多少个1.
同理,count(2),也可以,得到的值完全一样,count('x'),count('y')都是可以的。一样的理解方式。在你这个语句理都可以使用,返回的值完全是一样的。就是计数。
count(*),执行时会把星号翻译成字段的具体名字,效果也是一样的,不过多了一个翻译的动作,比固定值的方式效率稍微低一些

count(1)就是不指定具体字段,固定值。

网上找不到源码分析出count(1)到底做了什么。如果参考oracle数据库的解释,其实也不见得就能避免全表扫描

  

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
16天前
|
存储 SQL 关系型数据库
轻松入门MySQL:加速进销存!利用MySQL存储过程轻松优化每日销售统计(15)
轻松入门MySQL:加速进销存!利用MySQL存储过程轻松优化每日销售统计(15)
|
18天前
|
SQL 关系型数据库 MySQL
mysql一条sql查询出多个统计结果
mysql一条sql查询出多个统计结果
13 0
|
3月前
|
关系型数据库 MySQL 数据库
『 MySQL数据库 』聚合统计
『 MySQL数据库 』聚合统计
|
4月前
|
关系型数据库 MySQL
零基础带你学习MySQL—分组统计(十二)
零基础带你学习MySQL—分组统计(十二)
|
4月前
|
关系型数据库 MySQL
零基础带你学习MySQL—统计函数(合计函数)(十一)
零基础带你学习MySQL—统计函数(合计函数)(十一)
|
5月前
|
SQL 关系型数据库 MySQL
解决MySQL count统计数目错误的问题
解决MySQL count统计数目错误的问题
44 0
|
5月前
|
SQL 关系型数据库 MySQL
Mysql统计技巧:ON DUPLICATE KEY UPDATE用法
Mysql统计技巧:ON DUPLICATE KEY UPDATE用法
|
6月前
|
SQL 算法 关系型数据库
【MySQL系列】统计函数(count,sum,avg)详解
文章目录 🌈一、COUNT函数 创建一个表T1 1.COUNT函数的定义: 2.COUNT函数的使用方式: 1️⃣count(*) (1)count(*)定义: (2)具体使用: (3)
|
6月前
|
NoSQL 关系型数据库 MySQL
MySQL学习笔记-不同count统计的比较
MySQL学习笔记-不同count统计的比较
42 0
|
11天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)