前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySQL查询---COUNT函数

MySQL查询---COUNT函数

作者头像
创译科技
发布于 2019-10-29 07:50:10
发布于 2019-10-29 07:50:10
3.5K00
代码可运行
举报
文章被收录于专栏:Node开发Node开发
运行总次数:0
代码可运行

上一篇谈到了我们日常开发中经常需要用到的分页,在业务数据量不多的情况下,我们直接用limit指定偏移量就可以满足我们业务需求了,但是数据量大的时候使用limit指定偏移量性能会很低,因为需要全表检索。所以上一篇主要提到了几种可以优化分页的方案,而且分页业务一般都伴随着需要count函数查询总条数,所以本篇文章主要讲讲count函数的一般优化方案。

为什么分页一般要伴随查询数量?举个简单的例子:我们实现一个博客首页,我们按照十篇/页渲染,这样我们服务端必须查询给客户端当前页面10篇文章的数据,并且同时得告诉客户端一共有多少页的数据,所以这个时候的业务需求就变成分页 + count函数查询条数的逻辑了,而是大部分分页往往伴随着需要查询总数量的业务。

首先创建一个表,只有id,name,sex三个字段,使用存储过程随机插入100万条数据:

首先,我们先贴下最基本的count函数语法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(expr) from table;

可以看到count函数实际上需要传入expr,这个expr一般取值有以下三个:

  • 列名:会检索对应列值不为NULL的条数。
  • *:查询符合条件的行数,和列值是否为NULL无关,返回结果都会返回。
  • 常量:查询符合条件的行数,和列值是否为NULL无关,返回结果都会返回。

count(*),count(id)与count(1)效率对比

实际上对于count(*)和count(1)效率哪个更高,众说纷坛。我们可以先看看效率对比:

可以发现执行速度两条SQL语句是相差无几的,count(1)和count(*)都是查询全表数据行数,可能网上很多言论会说count(*)其实走的就是count(1)查询,所以使用count(1)查询可以节省转换时间,实际上无论count(*)还是count(1)完全一致,都是表示指定非空表达式,所以会查询所有符合条件的行数。为什么我会说这两个语句执行效果是一样的?因为Mysql官方文档写了这么一句话:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. 
There is no performance difference.

所以说实际上count(*)与count(1)在执行效率上是没有区别的,那既然没有区别我究竟要使用哪一个?我个人建议使用count(*),因为SQL92标准中制定count(*)为标准统计行数的语法,所以Mysql一直在不断地对count(*)做一定的优化。那有人说count(id)效率会不会更高?因为可以走主键索引,走索引查询效率不是应该更高?但是事实上count(id)查询效率会比count(*)更慢。我们可以测试下:

可能有人会纳闷我们添加索引列目的不就是为了提高查询效率?平时我们检索数据属于范围查询,查询指定的数据,所以走索引可以提高查询效率,但是count(id)选择索引基数大的主键索引肯定效率更低。因为主键索引和数据文件存放在一起,所以通过主键id取条数会检索数据文件,count(id)会检索整张表,然后遍历取到每一行数据的id,然后返回server层对每一行的id,不为空count就 + 1,而count(*)一样全表检索,但是不会取id值,因为在索引树就可以得到结果,所以count(id)需要取到数据再过滤id为null的数据效率方面肯定是慢上不少的。

count(*)优化

count(*)和count(1)没什么差别,但是执行时间都得1S多,而且数据量只是100万条,所以我们肯定需要进行适当的优化。因为count(*)实际上查询会使用最小字段的索引进行优化查询,但是因为目前我们表中只有一个主键索引,刚才也说过count(id)效率比count(*)低,所以默认不使用索引查询,我们可以使用explain测试下:

可以看到查询没有走任何索引,所以效率很低是必然的。而count(*)刚才说过会默认寻找最小字段的索引优化查询,所以我们给表增加一个status字段,弄成tinyint类型,并且添加二级索引,然后测试count(*)执行时间:

可以看到count(*)百万级数据成功被优化到0.32秒。完全符合我们的日常需求。所以说我们在需要取整表行数的时候就可以给表加一个非空的tinyint类型字段,并且添加二级索引,count(*)就会使用这个二级索引,优化查询速度。

count(col)

说完了count(*),我们知道了如果在需要返回全部行数时可以使用count(*),那接下来我们如果需要查询姓名不为空的总行数怎么做呢?我们可以加个where很快实现:

可以看到条数只有50万条,因为另外50万条name值为null所以被忽略了,执行时间1.38秒,这是我测试了多次取的最短时间。所以说百万级数据就需要秒级明显不符合需求,所以我们单字段筛选就可以使用count(字段名),会自动将字段为空的行剔除掉,我们可以测试下:

可以看到1.1秒可以查询到总条数,但是好像还是不满足我们的需求,一样还是秒级,我们使用explain查看下运行参数:

可以看到因为没有使用到索引,所以导致全表检索会扫描数据文件,现在我们对name字段添加一个索引,然后再测试:

可以看到只需要0.33秒就执行完成,一样使用explain查看下:

很显然,本次查询走索引了,加速查询的原因是什么呢?因为我们在name字段创建了一个二级索引,在无二级索引时,count操作只能全表检索数据。当我们通过二级索引统计总条数,无需扫描数据文件,因为二级索引存储的数据就是name字段的值与主键id值。所以在count(col)时就可以在字段上添加一个二级索引加快检索速率。

count函数指定where条件

这里一样得分两种情况:count(*)和count(col)。

  • count(*):where条件添加索引,就可以使用索引优化查询。例如我们刚才添加的type列表示用户账号是否可用,我们现在需要查询可用账户的总数量就可以这样写:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(*) from order_info where type = 0;

可以explain查看下运行参数可以发现确实使用到索引优化查询了:

  • count(col):查询列不为空的总条数并且添加where条件,就需要col添加索引并且where使用col进行条件限制,我们可以先来看下name添加索引但是where使用sex限制条件的情况:

然后我们查询name并且使用name限制条件看看是否可以使用索引优化查询:

可以看到查询的列名和where条件的列明一致就可以走索引查询提高效率了。所以说在数据量大的情况下要查询总条数我们要合理去利用索引优化查询。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序猿周先森 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL COUNT(*) COUNT(1) 与 COUNT(列) 的区别
over_clause 表示 COUNT 以窗口函数工作,MySQL 8.0 开始支持,这个不在本文展开,感兴趣的同学请参考 Section 14.20.2, “Window Function Concepts and Syntax”。
恋喵大鲤鱼
2024/05/09
4810
MySQL COUNT(*) COUNT(1) 与 COUNT(列) 的区别
一文搞清楚 MySQL count(*)、count(1)、count(col) 的区别
在工作中遇到count(*)、count(1)、count(col) ,可能会让你分不清楚,都是计数,干嘛这么搞这么多东西。
索码理
2022/09/20
1.6K0
一文搞清楚 MySQL count(*)、count(1)、count(col) 的区别
count(*) count(1)与count(col)的区别
count(*) 和count(1) 都是统计行数,而count(col) 是统计col列非null的行数
week
2019/06/11
4.5K0
最详细的 MySQL 执行计划和索引优化!
不管是工作中,还是面试中,关于mysql的explain执行计划以及索引优化,都是非常值得关注的。
田维常
2023/08/31
8990
最详细的 MySQL 执行计划和索引优化!
聊聊MySQL的COUNT()的性能,看看怎么最快?
基本职场上的程序员用来统计数据库表的行数都会使用count(*),count(1)或者count(主键),那么它们之间的区别和性能你又是否了解呢?
麦洛
2021/05/24
2.9K0
聊聊MySQL的COUNT()的性能,看看怎么最快?
MySQL索引知识结构
学习MySQL的知识,学习好索引是非常重要的,索引分类、索引如何正确添加、索引失效的场景、底层数据结构等问题是面试中必问的,就这些内容我们一起学习巩固下。
小许code
2023/06/01
7480
MySQL索引知识结构
MySQL索引(六)索引优化补充,分页查询、多表查询、统计查询
本文若未特意说明使用的数据表,均为 MySQL索引(四)常见的索引优化手段 中的示例表。
鳄鱼儿
2024/05/21
3590
MySQL索引(六)索引优化补充,分页查询、多表查询、统计查询
我的Mysql查询SQL优化总结
当我们遇到一个慢查询语句时,首先要做的是检查所编写的 SQL 语句是否合理,优化 SQL 语句从而提升查询效率。所以对 SQL 有一个整体的认识是有必要的。
程序员小明
2019/10/10
1.8K0
我的Mysql查询SQL优化总结
三高Mysql - Mysql索引和查询优化(偏实战部分)
实战部分挑选一些比较常见的情况,事先强调个人使用的是mysql 8.0.26,所以不同版本如果出现不同测试结果也不要惊讶,新版本会对于过去一些不会优化的查询进行优化。
阿东
2022/04/08
7930
三高Mysql - Mysql索引和查询优化(偏实战部分)
一文读懂MySQL的索引结构及查询优化
(同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论不一定适用于其他版本)
Python之道
2021/01/06
8790
Mysql面试题及千万级数据查询优化
今天在说Mysql查询优化之前,我先说一个常见的面试题,并带着问题深入探讨研究。这样会让大家有更深入的理解。
攻城狮的那点事
2019/09/17
1.4K0
Mysql面试题及千万级数据查询优化
MySQL 不同存储引擎下 count(星) count(1) count(field) 结果集和性能上的差异,不要再听网上乱说了
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2023/11/19
3590
MySQL 不同存储引擎下 count(星) count(1) count(field) 结果集和性能上的差异,不要再听网上乱说了
我被骗好久了!count(*) 性能最差?
当我们对一张数据表中的记录进行统计的时候,习惯都会使用 count 函数来统计,但是 count 函数传入的参数有很多种,比如 count(1)、count(*)、count(字段) 等。
小林coding
2022/02/11
4860
我被骗好久了!count(*) 性能最差?
MySQL索引(四)常见的索引优化手段
本文索引优化包含对 MySQL索引(三)explain实践,优化 MySQL 数据库查询性能 的一些补充。
鳄鱼儿
2024/05/21
1850
MySQL索引(四)常见的索引优化手段
浅谈MySQL分页查询
MySQL系列文章到目前已经更新十几篇,从数据类型谈到了备份恢复再到主从同步分库分表,从本篇开始,会花几篇重点谈谈MySQL基础部分,而本篇我们重点来讲讲我们日常开发中最常见的一种查询:分页查询。
创译科技
2019/10/29
3.9K0
浅谈MySQL分页查询
为啥count(*)会这么慢?
本没想着写这篇文章的,因为我觉得这个东西大多数有经验的开发遇到过,肯定也了解过相关的原因,但最近我看到有几个关注的技术公众号在推送相关的文章。实在令我吃惊!
科技新语
2023/01/03
1K0
【MySQL】count()查询性能梳理
通常情况下,分页接口一般会查询两次数据库,第一次是获取具体数据,第二次是获取总的记录行数,然后把结果整合之后,再返回。
后端码匠
2023/11/12
4590
MySQL面试题(最全、超详细)——定位慢查询、聚簇索引、覆盖索引、深分页优化、sql优化、并发事务问题、隔离级别、undo log与redo log、主从同步
查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志如果要开启慢查询日志,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
寻求出路的程序媛
2024/06/25
1.4K0
MySQL面试题(最全、超详细)——定位慢查询、聚簇索引、覆盖索引、深分页优化、sql优化、并发事务问题、隔离级别、undo log与redo log、主从同步
MySQL慢查询,一口从天而降的锅!
  记得那是一条查询SQL,数据量万级时还保持在0.2秒内,随着某一段时间数据猛增,耗时一度达到了2-3秒!没有命中索引,导致全表扫描。explain 中extra显示:Using where; Using temporary; Using filesort,被迫使用了临时表排序,由于是高频查询,并发一起来很快就把DB线程池打满了,导致大量查询请求堆积,DB服务器cpu长时间100%+,大量请求timeout。。最终系统崩溃。老板登场~
陈哈哈
2021/10/13
6030
原 荐 MySQL-性能优化-索引和查询优化
MySQL-性能优化-索引和查询优化 要知道为什么使用索引,要知道如何去使用好索引,使自己的查询达到最优性能,需要先了解索引的数据结构和磁盘的存取原理 参考博客:MySQL索引背后的数据结构及算法原理
秋日芒草
2018/06/06
7810
推荐阅读
相关推荐
MySQL COUNT(*) COUNT(1) 与 COUNT(列) 的区别
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验