直接回答

三者的差别在统计口径性能:count(字段) 统计该字段非 NULL 的行数;count() 和 count(1) 都统计总行数(不忽略 NULL)。InnoDB 下官方对 count() 做了专门优化,count(1) 语义上等价但不比它快,因此推荐统一写 count(*)

展开解析

  • count(字段):逐行取出该字段值,判断非 NULL 才计数。如果字段无索引,需要全表扫描并取值;有二级索引时优化器可能走索引。
  • count(1):不取任何字段,给每行塞一个常量 1 计数,不会为 NULL,等价于统计行数。
  • count(*):SQL 标准定义的"统计行数",MySQL 对 InnoDB 做了优化——不取整行数据,优先选择最小的二级索引遍历。

性能上:count() ≈ count(1) > count(主键) > count(普通字段)。InnoDB 因为 MVCC 不存总行数,count() 只能扫表/索引,大表上代价高;MyISAM 维护了行数,无条件的 count(*) 是 O(1)。

易错点:count(字段) 会漏掉 NULL 行,写统计 SQL 时若语义是"总行数"用了 count(字段) 就错了。大表精确计数可考虑汇总表或 Redis 计数。