MyISAM 引擎把一个表的总行数存在了磁盘上,如果不带where条件,执行 count(*) 的时候会直接返回这个数,效率很高;
innodb则不同:
对于 count(主键 id) 来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的, 就按行累加。
对于 count(1) 来说,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。 单看这两个用法的差别的话,你能对比出来,count(1) 执行得要比 count(主键 id) 快。因为从引擎返回 id 会涉及到解析数据行,以及拷贝字段值的操作。
对于 count(字段) 来说 1.如果这个“字段”是定义为 not null 的话, 一行行地从记录里面读出这个字段,判断不能为 null,按行累加; 2.如果这个“字段”定义允许为 null,那么执行的时候,判断到有可能是 null,还要把值取出来再判断一下,不是 null 才累加。
count(id)和count(字段)都是要把每一行的该字段值取出来,然后判断是否为空,那为什么count(id)的效率要高? 因为:count(id)可能会选择最小的索引来遍历,而count(字段)的话,如果字段上没有索引,就只能选主键索引
对于count(星)来说,并不会把全部字段取出来,而是专门做了优化,不取值。 count(星) 肯定不是 null,按行累加。
count(1)和count(*):5.7.18版本之前是扫描聚簇索引,之后是二级索引。虽然不取值,只计数。但是二级索引比聚簇索引需要扫描的页数相对来说更少,这也是一种优化
所以结论是:按照效率排序的话, count(字段)<count(主键 id)<count(1)≈count(星),所以我建议你,尽量使用 count(星)