count(主键)
在通过 count 统计有多少记录时,在 server 层会维护一个叫 count 的变量。server 层会循环向 InnoDB 读取一条记录,如果 count 函数指定的参数不为 NULL,那么就会对变量 count + 1,直到符合查询条件的全部记录被读完
以下语句为例:
|
|
当表中不存在二级索引时,InnoDB 会循环遍历聚簇索引,将读取到的记录返回给 server 层,然后读取记录中的 id 值来判断是否将变量 count +1
当存在二级索引时,由于相同数量的二级索引比聚簇索引占用的存储空间更小,因此优化器会选择二级索引进行遍历
count(1)
以下语句为例:
|
|
当不存在二级索引时,InnoDB 会便利聚簇索引,将读取到的记录返回给 server 层,但不会读取记录中任何字段的值。因为 count 函数的参数是 1,很明显 1 != NULL, 因此每读到一条数据,都会将变量 count +1
当存在二级索引时,遍历对象同样会变为二级索引
count(*)
对于 select * 来说,* 等同于所有字段值
但对于 count() 来说,实际等同于 count(0)。因此 count() 与 count(1) 的执行过程基本是一样的,没有什么差别
并且 MySQL 对于 count(*) 和 count(1) 有一个优化,如果存在多个二级索引的时候,优化器会选择 key_len 最小的二级索引进行扫描
count(字段)
count(字段) 相比以上几种的执行效率最差
为什么要通过遍历的方式来计数
在 InnoDB 中是支持事务的,因此在同一时刻的多个查询,由于多版本并发控制(MVCC)的原因,InnoDB 应该返回多少行也是不确定的