看同事写的SQL,统计订单数用count(0),另一边统计人数用count(1),他说听网上讲的这种写法快,我一时没答上来,只能回来把执行计划翻了一遍。

count括号里的东西只分两种

数据库看的不是你写的是0还是1还是星号,看的是它是不是列名。写常量0、常量1、常量abc,对数据库来说完全一样,就是数行,不去碰具体列数据。只有写列名,比如count(电话),它才会跳过空值去数。

SELECT COUNT(0) FROM orders;
SELECT COUNT(1) FROM orders;
SELECT COUNT(*) FROM orders;

这三条在MySQL和PG里结果一样,性能也一样。优化器早就认出来了,不存在谁更快。

唯一不一样的是count(列名)

  • count(星号):数所有行,包括空值,语义最清楚
  • count(常量):效果同上,写0写1都一样
  • count(列名):只数这列不为空的行,结果可能更小
  • count(distinct 列):去重后再数,走另一条逻辑
SELECT COUNT(phone) FROM users;
-- 只数填了电话的人,和上三条结果完全不同

线上出过好几次事故,有人把count(星号)改成count(某个字段),总人数突然少了一截,还以为丢数据了,其实是空值被排掉了。

性能到底看什么

慢查询跟括号里写什么没关系,看的是有没有索引、表有多大。InnoDB做全表count本来就慢,要提速得加二级索引、做汇总表,或者业务允许的话用估算值。

一句话取舍:团队统一用count(星号),语义直白;看到count(0)别慌,知道它跟星号一回事就行,别拿列名当行数用。