MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?
在 MySQL 中,COUNT(*)、COUNT(1) 和 COUNT(字段名) 的核心区别在于 统计逻辑 和 性能表现,具体如下:
1. 统计逻辑差异
| 函数形式 | 统计规则 | 
|---|---|
COUNT(*) | 统计表中所有行的数量,忽略字段值是否为 NULL(包括主键、非主键、NULL 值)。 | 
COUNT(1) | 逻辑与 COUNT(*) 完全相同,统计所有行的数量,1 是常量,不依赖具体字段。 | 
COUNT(字段名) | 仅统计该字段值 不为 NULL 的行数。若字段允许 NULL,结果可能小于前两者。 | 
2. 性能差异
COUNT(*) vs COUNT(1)
 
- 性能几乎一致:现代 MySQL 优化器会将 
COUNT(*)和COUNT(1)优化为相同的执行计划,直接统计行数,无需回表查询字段值。 - 例外情况:若表有二级索引,
COUNT(*)可能优先选择最小的索引扫描,而非主键索引。 
COUNT(字段名)
 
- 依赖字段是否 NULL: 
- 若字段 不允许 NULL(如主键或 
NOT NULL约束),结果与COUNT(*)相同。 - 若字段 允许 NULL,需过滤 NULL 值,可能略慢于 
COUNT(*)。 
 - 若字段 不允许 NULL(如主键或 
 - 索引优化: 
- 若字段有索引,
COUNT(字段名)可能直接扫描索引(比全表扫描更快)。 - 例如:
COUNT(id)(假设id是主键)可能比COUNT(*)更快,因为主键索引更紧凑。 
 - 若字段有索引,
 
3. 适用场景
| 场景 | 推荐函数 | 原因 | 
|---|---|---|
| 统计表的总行数(含 NULL 值) | COUNT(*) 或 COUNT(1) | 直观且性能最优,无需关心字段内容。 | 
| 统计某字段的非 NULL 值数量 | COUNT(字段名) | 明确过滤 NULL 值,结果可能更小。 | 
| 字段有索引且需统计非 NULL 值 | COUNT(字段名) | 可能利用索引加速,性能优于全表扫描。 | 
4. 示例验证
-- 创建测试表
CREATE TABLE test (id INT PRIMARY KEY,name VARCHAR(50),age INT NULL
);INSERT INTO test VALUES
(1, 'Alice', 25),
(2, NULL, 30),
(3, 'Bob', NULL);-- 统计总行数(含 NULL)
SELECT COUNT(*) FROM test;  -- 结果:3
SELECT COUNT(1) FROM test;   -- 结果:3-- 统计 name 字段非 NULL 的行数
SELECT COUNT(name) FROM test; -- 结果:2(Alice 和 Bob)-- 统计 age 字段非 NULL 的行数
SELECT COUNT(age) FROM test;  -- 结果:2(25 和 30)
 
总结
- 优先使用 
COUNT(*):语义清晰,性能可靠,适合大多数场景。 - 避免滥用 
COUNT(字段名):仅在需要过滤 NULL 值时使用,且注意字段索引情况。 COUNT(1)与COUNT(*)无本质区别:可视为等价写法,选择取决于代码风格。
我正在编程导航学习项目课程,和其他编程爱好者一起交流进步,你也一起来吧
 点击进入
