0%

MySQL count

MySQL 中 COUNT 函数的用法与区别详解

COUNT() 是 MySQL 中用于统计记录行数的聚合函数,但其参数不同(如 COUNT(*)COUNT(1)COUNT(列名))时,行为和性能存在差异。理解这些差异有助于写出更高效、准确的统计语句。

COUNT 函数的三种常见用法

1. COUNT(*)

  • 作用:统计所有记录的行数,包括 NULL 值(无论字段是否为 NULL,只要行存在就计数)。
  • 特点:
    • 不忽略任何行,包括包含 NULL 的行。
    • InnoDB 引擎对 COUNT(*) 进行了优化,会自动选择最小的索引(非主键索引优先)来加速统计,性能较好。

示例

1
2
-- 统计表中所有记录(包括字段为NULL的行)
SELECT COUNT(*) FROM doc; -- 结果:188(包含所有行)

2. COUNT(1)

  • 作用:统计所有记录的行数,原理与 COUNT(*) 类似(用常量 1 代替字段,只要行存在就计数)。
  • 特点:
    • 同样包含 NULL 值的行(因为 1 是常量,永远非 NULL)。
    • 在 InnoDB 中,COUNT(1)COUNT(*) 性能几乎一致,优化方式相同(优先使用最小索引)。

示例

1
2
-- 结果与 COUNT(*) 相同
SELECT COUNT(1) FROM doc; -- 结果:188(与 COUNT(*) 一致)

3. COUNT(列名)

  • 作用:统计指定列中非 NULL 值的行数(自动忽略 NULL 值)。
  • 特点:
    • 仅计数该列值不为 NULL 的行(若列允许 NULL,结果可能小于总行数)。
    • 若该列上有索引,会使用索引加速统计;否则会全表扫描,性能可能较差。

示例

1
2
-- 统计 source 列非 NULL 的行数(忽略 NULL 值)
SELECT COUNT(source) FROM doc; -- 结果:2(仅 2 行的 source 列非 NULL)

核心区别对比

用法 计数范围 是否忽略 NULL 值 性能优化(InnoDB) 适用场景
COUNT(*) 所有行(包括 NULL 行) 不忽略 自动选择最小索引(非主键优先),性能优 统计总记录数
COUNT(1) 所有行(包括 NULL 行) 不忽略 COUNT(*) 一致,性能几乎无差异 统计总记录数(写法习惯差异)
COUNT(列名) 指定列非 NULL 的行 忽略 依赖列是否有索引,无索引时性能较差 统计某列非空值的行数

性能对比与最佳实践

  1. COUNT(\*) vs COUNT(1)
    • 在 InnoDB 中,两者性能几乎无差异(优化逻辑相同)。
    • 推荐使用 COUNT(*),因为它是 SQL 标准中统计总行数的规范写法,可读性更高。
  2. COUNT(\*) vs COUNT(主键)
    • COUNT(主键) 会统计主键列非 NULL 的行数(主键永远非 NULL,结果与 COUNT(*) 一致)。
    • COUNT(*) 会选择更小的非主键索引,而 COUNT(主键) 强制使用主键索引(可能更大),因此 COUNT(*) 性能更优。
  3. COUNT(列名) 的注意事项
    • 若列允许 NULL,结果不等于总行数,需确认业务是否需要忽略 NULL
    • 为提升性能,建议在统计的列上创建索引(尤其是大表)。
  4. 避免 COUNT(1)COUNT(\*) 的误区
    • 网上传言 “COUNT(1)COUNT(*) 快” 是错误的,InnoDB 对两者的优化完全一致。
    • COUNT(*) 不会像传言那样 “展开所有字段”,而是直接统计行数,与字段数量无关。

示例分析

1
2
SELECT COUNT(*), COUNT(1), COUNT(source) FROM doc;
-- 结果:188, 188, 2
  • COUNT(*)COUNT(1) 均返回 188,说明表中共有 188 行(包括 source 列为 NULL 的行)。
  • COUNT(source) 返回 2,说明 source 列中只有 2 行的值非 NULL,其余 186 行为 NULL

欢迎关注我的其它发布渠道