Mysql count的原理你真的了解吗?
- 1、数据库引擎的区别
- 2、InnoDB中count的使用
- 3、innodb对select(\*)的优化/为什么select(\*)通过非聚集索引效率要高于聚集索引
面试问到说“你觉得count(*) 的效率怎么样?”,一般回复innodb对count(*)进行优化后效率显著提升,所以count(*)效率是最高的,但是面试官可能觉得你掌握情况一般
1、数据库引擎的区别
MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高; 但是如果是带条件的count,MyISAM也慢。
InnoDB 引擎就麻烦了,它执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。
2、InnoDB中count的使用
count的查询效率如下 count(普通字段) < count(主键) < count(*) ≈ count(1)
使用count的目的就是计算非空行数,如果使用的是普通字段,需要去判断该字段是否不为空,然后再去累计行数,而主键具备非空约束,可直接累计行数;注意,count(字段)都需要去遍历一整张表,然后将其中的字段取出来按行进行累加,
而count(1) 也会去遍历整张表但不会取数据,会放数字进去然后按行进行累加。
count(1)跟count(*)遍历整张表都不需要取字段,减少返回给服务器的操作,直接按行累加,所以它们的速度会比使用字段要快
3、innodb对select(*)的优化/为什么select(*)通过非聚集索引效率要高于聚集索引
count(字段非聚集索引)的索引结构(叶子节点保存的是(部分字段))会比count(主键,聚集索引,叶子节点保存的是row数据),那么count(字段)遍历整张表要快的多;
之所以快,是由于查询所访问的数据只占表的很小部分,如果访问的数据多了,那反而不如通过表扫描来得快,因为扫描用的是顺序IO,效率更高,比运用随机IO访问大量数据的效率高很多(is null 这种二义性查询索引失效的情况),所以通过非聚集索引,提升count(*) 的查询速度的本质在于,非聚集索引所占空间的大小往往,远小于聚集索引或堆表所占用的空间大小;
并且Mysql优化器会主动找到最小的索引数来遍历,保证逻辑正确的前提下,尽量减少扫描的数据量。
但是这个结论也不完全正常,如果非聚集索引的字段很长,或者说是联合索引,那可能效果会适得其反。
以上便是Mysql count(*)的使用原理以及InnoDb的优化策略的全部内容,如果有解读不当欢迎在评论区指出!