COUNT(*)是统计行数的正确、标准、高效写法;SUM(1)是语义错误的误用,不仅无性能优势,反而因需执行表达式求值与累加而多耗CPU,I/O相同但执行更慢。

SQL中SUM(1)不能替代COUNT(*),且无性能优势
直接结论:COUNT(*) 是统计行数的正确、标准、高效写法;SUM(1) 是语义错误的误用,不仅没有性能优势,在多数场景下反而更慢、更不可靠。
为什么SUM(1)执行更慢?看真实执行开销
Oracle 和 SQL Server 的实测 trace 数据显示:SUM(1) 比 COUNT(*) 多消耗 CPU(+3–4秒),而 I/O(逻辑读、物理读)完全一致。原因在于:
-
COUNT(*)被优化器识别为“纯行计数”,可跳过列值解析,甚至利用元数据缓存(如 InnoDB 的TABLE_ROWS)或索引快速路径; -
SUM(1)被当作数值聚合处理,引擎必须为每一行生成值1,再执行加法累加——多了一层表达式求值和累加逻辑,无法跳过扫描过程; - 即使走相同索引(如
INDEX FAST FULL SCAN),SUM的聚合阶段仍比COUNT的计数阶段重。
COUNT(*) 与 COUNT(1) 的区别在哪?
COUNT(1) 和 COUNT(*) 在现代数据库(MySQL 8.0+、PostgreSQL、SQL Server、Oracle)中行为完全等价,优化器均将其转为行计数路径。但关键差异在于语义:
-
COUNT(*)明确表达“统计关系的基数”,符合 SQL 标准,任何 DBA 或新人一眼能懂; -
COUNT(1)是COUNT(表达式)形式,虽被优化,但暗示“我对某列/表达式做非空计数”,容易引发困惑(比如误以为它会跳过 NULL 行——其实不会); -
SUM(1)完全不属于计数语义范畴:它是对常量求和,不是对行存在性计数,别人读到会本能质疑“你在加什么?为什么不用 COUNT?”。
什么时候真该用 SUM?只在条件计数场景
SUM 的正当用途是带条件的布尔计数,例如统计支付成功的订单数:
SELECT SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) AS paid_count FROM orders;
这比 COUNT(CASE WHEN status = 'paid' THEN 1 END) 更常见,因为 SUM 天然处理 0,结果更稳定。但注意:
- 这里
SUM的参数是条件表达式,不是固定常量1; - MySQL 支持隐式布尔转整数(
SUM(status = 'paid')),但这属于方言,不跨库; -
SUM(1)没有条件逻辑,纯属冗余计算,没有任何业务含义支撑。
真正容易被忽略的是:语义清晰性不是“写起来顺手”的问题,而是协作成本。一个 SUM(1) 可能让同事花三分钟确认“它是不是漏了 WHERE 条件”,而 COUNT(*) 不需要解释。


















