MySQL 中 count(*)、count(1) 和 count(字段名) 的区别
在 MySQL 中,COUNT()
函数用于统计记录数。虽然 COUNT(*)
、COUNT(1)
和 COUNT(字段名)
的功能类似,但它们在执行逻辑和结果上有所不同。
1. count(*)
特点
- 统计表中所有行的数量,包括
NULL
值。 - 执行时不会忽略任何行。
- 通常是统计总行数的首选方式,因为其优化程度最高。
执行原理
- MySQL 会将
COUNT(*)
优化为统计行数操作,不需要额外读取数据内容。 - 引擎级别的优化使其性能优于
COUNT(字段名)
。
适用场景
- 统计整个表的总行数时使用。
2. count(1)
特点
- 统计所有行的数量,同样包括
NULL
值。 1
只是一个常量,与表中的具体字段无关。
执行原理
- MySQL 会将
COUNT(1)
优化为COUNT(*)
,执行时效果基本相同。 - 逻辑上是检查每行是否存在,判断为有效行后计数。
适用场景
- 与
COUNT(*)
类似,但在语义上可以明确表示对行数的统计。
3. count(字段名)
特点
- 统计指定字段非空值的行数。
- 只会统计字段值不为
NULL
的行。
执行原理
- 查询过程中会判断该字段是否为
NULL
,只有非NULL
的行才会被计数。 - 若字段上存在索引,则
COUNT(字段名)
可直接通过索引计算,性能较好。
适用场景
- 当需要统计某字段非空值的数量时使用。
4. 示例
假设有一个 users
表,内容如下:
id | name | age |
---|---|---|
1 | Alice | 25 |
2 | Bob | NULL |
3 | NULL | 30 |
4 | Carol | NULL |
5 | NULL | 35 |
(1) COUNT(*)
SELECT COUNT(*) FROM users;
结果:
5
说明:统计所有行数,包括 NULL
。
(2) COUNT(1)
SELECT COUNT(1) FROM users;
结果:
5
说明:统计所有行数,与 COUNT(*)
结果一致。
(3) COUNT(name)
SELECT COUNT(name) FROM users;
结果:
3
说明:统计 name
列中非 NULL
的值,结果为 3。
(4) COUNT(age)
SELECT COUNT(age) FROM users;
结果:
3
说明:统计 age
列中非 NULL
的值,结果为 3。
5. 性能对比
-
COUNT(*)
和COUNT(1)
- 性能上几乎无差别,因为都由 MySQL 优化为相同的行统计操作。
- 优先使用
COUNT(*)
,更直观且语义明确。
-
COUNT(字段名)
- 会判断字段是否为
NULL
,性能可能略低于COUNT(*)
和COUNT(1)
。 - 如果字段上有索引,性能会更优。
- 会判断字段是否为
6. 总结
类型 | 是否统计 NULL |
优化程度 | 使用场景 |
---|---|---|---|
COUNT(*) |
是 | 最高 | 统计表中总行数 |
COUNT(1) |
是 | 高 | 统计表中总行数(与 COUNT(*) 等效) |
COUNT(字段名) |
否 | 中等(视索引而定) | 统计字段非空值的行数 |
推荐:
- 默认使用
COUNT(*)
,语义清晰且优化程度最高。 - 如果需要统计字段的非空值数量,使用
COUNT(字段名)
。