select count(1)          as male_num
      ,round(avg(gpa),1) as avg_gpa
from user_profile
where gender = 'male';
  • COUNT(*)COUNT(1)几乎完全一样(统计所有行,包含 NULL),现代数据库中性能无差别。
  • COUNT(字段)不一样(只统计该字段不为 NULL 的行)。

COUNT(*) vs COUNT(1):到底哪个快?

在早期的数据库版本(如旧版 MySQL MyISAM 引擎)中,有人认为 COUNT(1)COUNT(*) 快,因为 * 需要解析所有列。

但在现代数据库(MySQL 5.7/8.0+, PostgreSQL, Oracle, SQL Server)中:

  • 优化器智能处理:数据库优化器非常聪明,它发现你只是要计数,根本不会去读取具体的列数据。
  • 执行计划一致:查看 EXPLAIN 执行计划,你会发现 COUNT(*)COUNT(1) 生成的执行计划完全一模一样
  • 结论性能没有区别

最佳实践建议:

  • 推荐使用 COUNT(*)
  • 原因:这是 SQL 标准写法,语义最清晰(“我要统计行数”),可读性最好。COUNT(1) 显得有点多余且带有“过度优化”的老旧味道。

特殊场景:COUNT(DISTINCT 字段)

还有一个变体是 COUNT(DISTINCT 字段)

  • 规则:统计该字段非 NULL不重复 的值个数。
  • 性能:通常比普通的 COUNT 慢,因为它需要进行去重排序或哈希操作。

总结建议

  1. 统计总行数:无脑用 COUNT(*)
  2. 统计某列有效数据量(排除空值):用 COUNT(字段名)
  3. 统计某列不重复的有效数据量:用 COUNT(DISTINCT 字段名)
  4. 不要纠结 COUNT(1):它和 COUNT(*) 一样,但 COUNT(*) 更标准。