前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >搞定面试官 - MySQL 中,对于 COUNT() 如何正确使用?

搞定面试官 - MySQL 中,对于 COUNT() 如何正确使用?

作者头像
周三不加班
发布2023-03-15 15:46:56
4550
发布2023-03-15 15:46:56
举报
文章被收录于专栏:程序猿杂货铺程序猿杂货铺

‍‍大家好,我是程序员啊粥。

相信在大家的工作中,有很多的功能都需要用到 count(*) 来统计表中的数据行数。同时,对于一些大数据的表,用 count 都是瑟瑟发抖,往往会结合缓存等进行处理。

那么,我们今天就来分析一下,在 InnoDB 中,关于 count 的一些处理措施和优化。

常见的 count 三种使用方式

  • count(*)
  • count(主键 Id)/count(某个字段)
  • count(1)

首先 count(*)、count(主键 Id)/count(某个字段) 和 count(1) 都表示返回满足条件的结果集的总行数。

各自用法的差异

他们的差异在于:count(字段)表示返回满足条件的数据行里面,参数“字段”不为 NULL 的总条数,而 count(1) 会统计表中的所有的记录数,包含字段为 NULL 的记录,但它是用 1 代替了所有列,不在关注表中具体列的情况,count(*) 包括了所有的列,相当于行数,在统计结果的时候,它同样不会忽略为 NULL 的值。

接下来,我们就一个个地来看看。

COUNT(主键ID)

对于 count(主键 id) 来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。

COUNT(1)

对于 count(1) 来说,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。

单看这两个用法的差别的话,相信你能对比出来,count(1) 执行得要比 count(主键 id) 快。因为从引擎返回 id 会涉及到解析数据行,以及拷贝字段值的操作,少一步操作就能少一些时间。

同时对于 count(字段) 来说:如果这个“字段”是定义为 Not Null 的话,一行行地从记录里面读出这个字段,判断发现这个字段不能为 Null,那么直接按行累加;但是如果这个“字段”定义允许为 Null 的话,那么执行的时候,还要把具体的字段值取出来再判断一下,不是 Null 才能进行累加。

COUNT(*)的优化

count(*) 是例外,MySQL 专门对其做出了优化,MySQL 每发布一个新版本,都会放出相应的 Release Notes,我们注意到 5.7.2 版本的发布说明中提到:

InnoDB: SELECT COUNT(*) FROM t statements now invoke a single handler call to the storage engine to scan the clustered index and return the row count to the Optimizer. Previously, a row count was typically performed by traversing a smaller secondary index and invoking a handler call for each record. A single handler call to the storage engine to count rows in the clustered index generally improves SELECT COUNT(*) FROM t performance. However, in the case of a large clustered index and a significantly smaller secondary index, performance degradation is possible compared to performance using the previous, non-optimized implementation. For more information, see Limits on InnoDB Tables.

简单地说就是:COUNT(*) 会选择聚集索引,进行一次内部 handler 函数调用,即可快速获得该表行数

所以,它也不存在需要取值判断是否为 Null 的计算操作,可以说效率有很大的提高。

总结

所以结论是:按照效率排序的话:

count(字段)<count(主键 id)<count(1)≈count(*)

所以我建议你,尽量使用 count(*)。

而不是受我们惯性思维的影响,觉得 count(*) 可能和 select(*) 一样,效率会很低,反之,这是效率最高的。

当然,你如果实际中遇到了大数据量的表,可能把具体的行数缓存下来,或者专门建立一张表来存储这个 count() 值,而不是每次都去表里扫描一次。

好了,今天的内容到此就结束了,关于 count() 的用法,你用对了嘛?

评论区留言我们一起讨论哇!

我是程序员阿粥,我们一起在技术世界中向上生长。

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

本文分享自 程序员啊粥 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档