SQL 中三种 COUNT 函数的区别
1. count(*):统计所有行数
- 统计逻辑:统计满足条件的所有行数,不关心具体的列值。
- NULL值处理 :不忽略 NULL 值。即使某行的所有字段都是 NULL,也会被统计。
- 执行性能:⭐⭐⭐⭐⭐ (最优)。现代数据库(如MySQL InnoDB)对其有专门优化,通常选择最小的二级索引进行扫描,无需读取完整行数据。
2. count(1):统计所有行数
- 统计逻辑 :传入常量
1,为每一行分配固定值1并计数。效果等同于统计总行数。 - NULL值处理 :不忽略 NULL 值,结果与
count(*)完全一致。 - 执行性能 :⭐⭐⭐⭐⭐ (与
count(*)一致)。在现代数据库优化器中,count(1)会被自动转换为与count(*)相同的执行逻辑,两者性能几乎没有差别。
3. count(单个字段):统计该字段非NULL的行数
- 统计逻辑:专门统计指定字段有值的行数。
- NULL值处理 :会忽略 NULL 值。如果该字段值为 NULL,该行会被过滤掉,不参与计数。
- 执行性能 :⭐⭐ (依赖索引,最差)。
- 有索引:扫描该二级索引,并额外判断是否为 NULL。
- 无索引:只能进行全表扫描,读取每一行该字段的值进行判断,性能最差。
核心对比总结
| 对比维度 | count(*) |
count(1) |
count(单个字段) |
|---|---|---|---|
| 统计结果 | 所有行数(含NULL) | 所有行数(含NULL) | 仅该字段非NULL的行数 |
| 执行效率 | ⭐⭐⭐⭐⭐ (最优) | ⭐⭐⭐⭐⭐ (与*一致) | ⭐⭐ (依赖索引,最差) |
| 语义 | 统计行数 | 统计行数 | 统计某列的非空数据量 |
最佳实践建议
- 统计表的总行数 ,请无脑使用
count(*)。它是 SQL 标准语法,语义明确且性能最优。 - 只有明确需要统计某个特定字段非空值的数量 时,才使用
count(单个字段)。注意:如果该字段允许为 NULL,统计结果可能少于总行数。 - 网上流传的"
count(1)比count(*)快"的说法在现代数据库中已不再成立,两者性能基本一致。