MySQL 中COUNT(*),COUNT(1),COUNT(普通字段),COUNT(索引字段)的效率和区别?

目录

1. 结论

2. 在MyISAM 存储引擎中

3. InnoDB 存储引擎中


1. 结论

结论一:COUNT(*)和COUNT(1)都是对所有结果进行COUNT,二者区别不大,效率没有明显差别;

结论二:COUNT(普通字段)得到的结果可能与COUNT(1),COUNT(*),COUNT(主键字段)不一样,因为普通字段可能为NULL,为NULL则不会被统计进去,后面三者则是按行统计,只要一行中有一个字段不为NULL就会被统计进去;

结论三:执行效率 COUNT(*) = COUNT(1) > COUNT(主键字段) > COUNT(普通字段);

2. 在MyISAM 存储引擎中

在MyISAM存储引擎,因为每张表中都有一个 mate 信息记录 row_count 的值,不需要进行重新计算,所以时间复杂度为O(1);

而且,MyISAM 存储引擎中只有表级锁,能够确保数据的准确性和唯一性

3. InnoDB 存储引擎中

(1)在InnoDB存储引擎中,表中没有具体的值来记录行数,需要进行全表扫描,都是需要用的时候再去进行COUNT计算,所以时间复杂度为O(n)。原因就是因为InnoDB存储引擎的行锁支持高并发和MVCC的版本控制,会导致统计数据不准确,不像MyISAM那样是表级锁,一次只能有一个线程操作。

(2)在有非聚簇索引的情况下,COUNT(1),COUNT(*),COUNT(主键字段)都是优先通过非聚簇索引统计数据,因为非聚簇索引的B+树不存储完整数据,只有索引列和主键值,数据量小,IO成本低,是优化器会优先选择的做法,并且如果有多个非聚簇索引,优化器会选择索引列最小(key_len最小)成本最低的一个来进行统计。COUNT(普通字段)就需要通过聚簇索引的B+树来进行统计,因为非聚簇索引的B+树中没有普通字段,无法通过非聚簇索引统计记录数。

(3)在没有非聚簇索引的情况下,COUNT(1),COUNT(*),COUNT(普通字段),COUNT(索引字段)都是通过聚簇索引来进行统计,如果字段为NULL也是统计不进去的,所以COUNT(普通字段)统计的结果一定小于等于 COUNT(1),COUNT(*),COUNT(索引字段) 的结果。

你可能感兴趣的:(mysql,数据库)