MySQL-count(1)、count(*)与count(列名)的执行区别

https://time.geekbang.org/column/article/72775

MyISAM引擎

因为该引擎没有事务和MVCC,因此会保存一个行数的变量,当在执行无where条件的行数统计时,就会直接返回该行数变量。

当然如果有where条件,还是要逐行扫描判断,得到满足条件的行数。

innodb引擎

因为innodb的MVCC机制,导致不同事务在同一时刻看到的数据都是不一样的,因此统计到的行数也是不一样的。所以没办法保存一个行数的变量,必须每次去实时的扫描统计。但是不同的count语句的统计逻辑和优化也不一样。

count(*)

该语句会选择一个空间最小的索引进行扫描,最后给server层返回一个行数

count(id)

该语句会扫描主键索引,每扫描一行就给server层返回该行id,server层每得到一个id就将当前行数加1,最后得到了一个总的行数

count(1)

该语句会扫描主键索引,每扫描一行就给server层返回1,server层将这些1不断相加,最后得到了一个总的行数

count(字段)

该语句扫描该字段,每扫描一行就会该字段值,server层收到该数据之后会判断是否为空,不为空才会将当前行数加1,最后得到一个总的行数。

可知该语句只能得到该字段不为空的总行数,也可以跟count(*)返回行数相减得到该字段为空的行数

show table status

索引统计的值是通过采样来估算的。实际上,TABLE_ROWS 就是从这个采样估算得来的,因此它也很不准。有多不准呢,官方文档说误差可能达到 40% 到 50%。所以,show table status 命令显示的行数也不能直接使用。

所以结论是:按照效率排序的话,count(字段)<count(主键 id)<count(1)≈count(*),所以我建议你,尽量使用 count(*)。

posted on 2020-03-28 11:54  simple_孙  阅读(3927)  评论(0编辑  收藏  举报

导航