飞利浦·斯塔克|MySQL统计总数就用count,别花里胡哨的《死磕MySQL系列 十》( 二 )


问题:为什么存储的有数据怎么不用?
这个图的数据怎么得到的 , 我想你应该知道了 , 没错 , 就是执行show table status \\G;得来的 。

那为什么innodb存储引擎不直接使用Rows这个值呢?
还记不记得在第六期文章中 , 五分钟 , 让你明白MySQL是怎么选择索引《死磕MySQL系列 六》
先不要返回去看这篇文章 , 看下上文图中最后查到的数据总条数是多少 。
你会发现这两个统计的数据是不一致的 , 因此这个值肯定是不可以用的 。
具体原因
因为Rows这个值跟索引基数Cardinality一样 , 都是通过采样统计的 。
采样规则
首先 , 会选出N个数据页 , 然后统计每个数据页上不同的值 , 最后得到一个平均值 。 再用这个平均值乘索引的数据页总数得到的就是索引基数 。
并且这个索引基数也不是一成不变的 , 会随着数据持续增删改 , 当变更的数据超过1/M时才会触发 , M值是根据MySQL参数innodb_stats_persistent得到的 , 设置为on是10 , off是16 。
在MySQL8.0这个默认值为on , 也就是说当这张表的数据变更超过总数据的1/10就会重新触发采样统计 。
三、不同count的用法以下所有的结论都基于MySQL的Innodb存储引擎 。
count(主键ID)
innodb引擎会遍历整张表 , 把每一行的ID值都那出来 , 然后返回给server层 , server层拿到ID后 , 判断不可能为空 , 进行累加 。
count(1)
同样遍历整张表 , 但不取值 , server层对返回的每一行 , 放一个数字1进去 , 判断是不可能为空的 , 按行累加 。
count(字段)
【飞利浦·斯塔克|MySQL统计总数就用count,别花里胡哨的《死磕MySQL系列 十》】分为两种情况 , 字段定义为not null和null

  • 为not null时:逐行从记录里面读出这个字段 , 判断不能为null , 累加
  • 为 null时:执行时 , 判断到有可能是null , 还要把值取出来再判断一下 , 不是null才累加 。
**count()
这个哥们就厉害了 , 不是带了就把所有值取出来 , 而是MySQL做了专门的优化 , count ()肯定不是null , 按行累加 。
结论
按照效率的话 , 字段 < 主键ID < 1 ~ , 最好都使用count() , 别花里胡哨的 。
五、总结本期文章就一句话 , 统计总数就用count(*) , 别花里胡哨的
坚持学习、坚持写作、坚持分享是咔咔从业以来所秉持的信念 。 愿文章在偌大的互联网上能给你带来一点帮助 , 我是咔咔 , 下期见 。