在开发系统的时候,你可能经常需要计算一个表的行数,这时候你可能会想,一条 select count(*) from t 语句不就解决了吗?
但是,你会发现随着系统中记录数越来越多,这条语句执行得也会越来越慢。
MyISAM 引擎:把一个表的总行数存在了磁盘上,因此执行count(*) 的时候会直接返回这个数,效率很高。
InnoDB 引擎:它执行count(*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。
这里,首先你要弄清楚 count() 的语义。count() 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是 NULL,累计值就加 1,否则不加。最后返回累计值。
所以,count(*)、count(主键 id) 和 count(1) 都表示返回满足条件的结果集的总行数;而 count(字段),则表示返回满足条件的数据行里面,参数“字段”不为 NULL 的总个数。
1. count(id)
InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。
2. count(1)
InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。
3. count(字段)
4. count(*)
它并不会把全部字段取出来,而是专门做了优化,不取值。count(*) 肯定不是 null,按行累加。
按照效率排序的话,count(字段)<count(id)<count(1)≈count(*)
所以我建议你,尽量使用 count(*)。
但是对于数据量庞大的库来说,count(*)还是会变得很慢,这个时候应该怎么办呢?欢迎评论~