count(1)、count(具体字段)和count(*)究竟有什么区别?

简介: count(1)、count(具体字段)和count(*)究竟有什么区别?

在MySQL中统计数据表的行数,可以使用三种方式:select count(*) select count(1) 和 select count(具体字段),使用这三者之间的查询效率是怎样的?


前提:如果你要统计的是某个字段的非空数据行数,则另当别论,毕竟比较执行效率的前提是结果一样才可以。


假设我们有表people,有100万条数据。

CREATE TABLE `people` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `zipcode` varchar(20) COLLATE utf8_bin DEFAULT NULL,
  `firstname` varchar(20) COLLATE utf8_bin DEFAULT NULL,
  `lastname` varchar(20) COLLATE utf8_bin DEFAULT NULL,
  `address` varchar(50) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `zip_last_first` (`zipcode`,`lastname`,`firstname`)
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin


那么如下三条SQL统计行数结果为:

# 1000000 条数据  414ms
select count(*) from people p ; 
# 1000000 条数据
select count(1) from people p ;
# 999999条数据
select count(zipcode) from people p ;



count(*) 和 count(1)的执行计划

explain select SQL_NO_CACHE count(*) from people p ;


cc78dcb64b5c4031bb768c6f249e366d.png

explain  select SQL_NO_CACHE count(1) from people p ;

7b7e8c89570d4856adbff8d0d18c3206.png

可以发现,二者执行计划是一模一样。对比二者的查询成本也能说明这一点:


从统计数据行结果来讲


count(*) 和 count(1) 都是对所有结果进行count,二者本质丧没有区别(二者执行时间可能略有差别,不过你还是可以把它两的执行效率看成是相等的)。如果有 where 子句,则是对所有符合筛选条件的数据行进行统计。如果没有where子句,则是对数据表的数据行数进行统计。


count(具体字段) 则会过滤掉为null的数据。


如果是MyISAM存储引擎,统计数据表的行数只需要O(1)的复杂度,这是因为每张MyISAM的数据表都有一个 meta 信息存储了 row_count 值,而一致性则由表级锁来保证。


如果是InnoDB存储引擎,因为InnoDB支持事务,采用行级锁和MVCC机制,所以无法像MyISAM一样,维护一个 row_count 变量,因此需要采用 扫描全表 ,进行循环+计数的方式来完成统计。

使用什么索引进行统计?


在InnoDB引擎中,如果采用 count(具体字段) 来统计数据行数,要尽量采用二级索引。因为主键采用的索引是聚簇索引,聚簇索引包含的信息很多,明细会大于二级索引(非聚簇索引)。


对于count(*) 和 count(1) 来说,他们不需要查找具体的行,只是统计行数,系统会 自动 采用占用空间更小的二级索引来进行统计。


如果有多个二级索引,会使用 key_len 小的二级索引进行扫描。当没有二级索引的时候,才会采用主键索引来进行统计。

目录
相关文章
|
2月前
|
前端开发 Java Nacos
application.yml和bootstrap.yml这两个配置文件有什么区别?
`bootstrap.yml` 与 `application.yml` 是 Spring Boot/Cloud 项目中的两类配置文件。前者用于应用启动前加载,主要配置远程配置中心(如 Nacos)、加密等关键信息,优先级高;后者是默认主配置,用于常规配置如端口、数据库等。自 Spring Boot 2.4+ 起,默认不再启用 `bootstrap` 机制,推荐使用 `spring.config.import` 在 `application.yml` 中统一导入配置,以简化流程、降低复杂度。纯 Spring Boot 应用不加载 `bootstrap.yml`。
312 0
|
JavaScript 前端开发
js中模糊搜索 模糊匹配如何实现?
js中模糊搜索 模糊匹配如何实现?
|
NoSQL Java MongoDB
Spring Boot中MongoDB的使用和实战
Spring Boot中MongoDB的使用和实战
422 0
|
6月前
|
存储 机器学习/深度学习 数据采集
数据湖 vs 数据仓库:大厂为何总爱“湖仓并用”?
数据湖与数据仓库各有优劣,湖仓一体架构成为趋势。本文解析二者核心差异、适用场景及治理方案,助你选型落地。
数据湖 vs 数据仓库:大厂为何总爱“湖仓并用”?
|
10月前
|
JavaScript 前端开发 API
什么是声明式UI什么是命令式UI?鸿蒙ArkTS为什么是声明式UI-优雅草卓伊凡
什么是声明式UI什么是命令式UI?鸿蒙ArkTS为什么是声明式UI-优雅草卓伊凡
309 12
什么是声明式UI什么是命令式UI?鸿蒙ArkTS为什么是声明式UI-优雅草卓伊凡
|
云安全 网络安全 CDN
阿里云CDN遇到攻击?别慌,教你如何应对!
阿里云CDN遇到攻击?别慌,教你如何应对!
|
消息中间件 存储 Kafka
Fluss: First Impression
Fluss: First Impression
292 0
|
缓存 Linux C++
map异常崩溃分析汇总
文章讨论了std::map和std::set在某些情况下崩溃的原因,包括结构体字节对齐问题、多线程资源同步问题、以及比较器的实现问题,并提供了相应的解决方案。
554 0
count(*) 和 count(1)和count(列名)区别
count(*) 和 count(1)和count(列名)区别
760 0
|
安全 测试技术 API
如何实现API接口的自动化测试?
实现API接口的自动化测试涉及多个关键步骤:确定测试范围和目标、编写测试用例、选择自动化测试工具、搭建测试环境、编写测试脚本、执行测试、分析结果和回归测试。选择合适的工具和考虑团队熟悉度是成功的关键。常用工具包括Postman、JMeter和SoapUI。通过这些步骤和工具,可以有效提高测试效率和质量,确保API的稳定性和可靠性。

热门文章

最新文章