MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?

基于InnoDB引擎

1. count(*)

统计满足条件的总行数 ,会统计包含NULL的行,不会忽略null。

MySQL优化层做了专门优化,不会读取行的全部数据,只统计行是否存在。

2. count(1)

传入常量1,每一行都不为null,效果等价统计总行数,同样统计全部行数,不会忽略NULL。

早期版本有性能差异,现在MySQL优化后,count(*) 和 count(1) 性能几乎没有差别。

3. count(字段名)

统计该字段不为NULL的行数,如果这个字段的值是NULL,这一行会被过滤掉,不参与计数。

示例:

id name
1 张三
2 NULL
3 李四
sql 复制代码
select count(*) from user;    --结果:3,统计所有行
select count(1) from user;    --结果:3
select count(name) from user; --结果:2,name为null那一行被排除

底层执行差异

  1. count(*)

    InnoDB会找最小的二级索引来扫描,不需要读取聚簇索引完整行,只统计行数,效率很高。

  2. count(1)

    优化器内部会转化成和count()相近逻辑,遍历索引,每行填个1做计数,现代版本性能和count()基本一致。

  3. count(字段)

  • 如果字段有索引:扫描这个二级索引,判断字段值是否为NULL,非NULL才计数;
  • 如果字段没有索引:只能扫描聚簇索引(全表),读取每一行这个字段的值做判断,性能很差。

⚠️注意:count(主键id):id不会为null,统计全部行数。但会读取主键字段的值,性能略低于count(*)。

常见误区

  1. 网上说count(1)比count(*)快,旧版本,现在不成立,MySQL已经做优化;
  2. count(字段)会跳过NULL,业务很容易踩坑,如果要统计行数,不要用count(普通字段);
  3. MyISAM不带where条件的count(*)会直接返回表元数据,速度极快;InnoDB没有这个特性,必须扫描索引统计行数,因为MVCC多版本,不同事务看到行数不一样。

总结:

  • 统计行数优先使用 count(*),MySQL专门优化,性能最优;
  • count(1) 结果和count(*)一致,新版本性能基本无差别;
  • count(字段) 只统计字段非NULL的数据,如果字段允许为null,统计结果会少一部分;无索引时性能很差。
相关推荐
这个DBA有点耶41 分钟前
函数索引的“完全一致”有多苛刻:写法、字符集、类型,差一处就失效
数据库·mysql·代码规范
星恒随风42 分钟前
MySQL 从零入门(三):表的约束详解
linux·服务器·数据库·笔记·mysql
Alluxio1 小时前
Alluxio + OCI:为 AI 工作负载实现亚毫秒访问延迟与可扩展吞吐
运维·数据库·人工智能·分布式·缓存·ai·语言模型
数据库急诊室_阿哲5 小时前
一次加索引建议的复核记录:从报告到签字
数据库·ai数据库
青瓦梦滋6 小时前
Redis主从复制
服务器·数据库·redis·缓存·bootstrap
慧都小妮子7 小时前
Wyn商业智能国产数据库适配:数据接入、分析缓存与审计日志验证清单
数据库·数据分析·数据可视化·审计日志·商业智能
Joy T8 小时前
Redis Lua 原子限流:Lua 脚本、竞态条件与并发控制
数据库·redis·lua·限流·竞态条件·redis scripting
杨凯凡8 小时前
MySQL 死锁怎么排查?InnoDB 锁等待与 Spring Boot 整事务重试实战
数据库·spring boot·mysql
Aloudata8 小时前
Claude 做数据分析的这两年:一份复盘与发展线索
大数据·数据库·人工智能·数据挖掘·数据分析·dataagent
Decay__8 小时前
01_SQLServer 体系架构全解 —— 实例进程、关系引擎、SQLOS 与事务日志深入
运维·数据库·sql·mysql·架构