Mysql中count()使用的问题?

简介:

count()函数用来统计表的行数,也就是统计记录行数,很好理解的,但面试你这么说就有点单薄了。

count()函数具体情况下的各种分析:

 

各类面试题总结了一下,应该遇到的话不会怕了:

1)为什么 InnoDB 不把总条数记录下来,查询的时候直接返回呢?

因为 InnoDB 使用了事务实现,而事务的设计使用了多版本并发控制,即使是在同一时间进行查询,得到的结果也可能不相同,所以 InnoDB 不能把结果直接保存下来,因为这样是不准确的。

2)能否使用 show table status 中的表行数作为表的总行数直接使用?为什么?

不能,因为 show table status 是通过采样统计估算出来的,官方文档说误差可能在 40% 左右,所以 show table status 中的表行数不能直接使用。

3)InnoDB 和 MyISAM 执行 select count(*) from t,哪个效率更高?为什么?

MyISAM 效率最高,因为 MyISAM 内部维护了一个计数器,直接返回总条数,而 InnoDB 要逐行统计。

4)在 MySQL 中有对 count(*) 做优化吗?做了哪些优化?

count(*) 在不同的 MySQL 引擎中的实现方式是不相同的,在没有 where 条件的情况下:

  • MyISAM 引擎会把表的总行数存储在磁盘上,因此在执行 count(*) 的时候会直接返回这个这个行数,执行效率很高;
  • InnoDB 引擎中 count(*) 就比较麻烦了,需要把数据一行一行的从引擎中读出来,然后累计基数。

但即使这样,在 InnoDB 中,MySQL 还是做了优化的,我们知道对于 count() 这样的操作,遍历任意索引树得到的结果,在逻辑上都是一样的,因此,MySQL 优化器会找到最小的那颗索引树来遍历,这样就能在保证逻辑正确的前提下,尽量少扫描数据量,从而优化了 count() 的执行效率。

5)在 InnoDB 引擎中 count(*)、count(1)、count(主键)、count(字段) 哪个性能最高?

count(字段)<count(主键 id)<count(1)≈count(*) 题目解析:

  • 对于 count(主键 id) 来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。
  • 对于 count(1) 来说,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。
  • 对于 count(字段) 来说,如果这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,判断不能为 null,按行累加;如果这个“字段”定义允许为 null,那么执行的时候,判断到有可能是 null,还要把值取出来再判断一下,不是 null 才累加。
  • 对于 count(*) 来说,并不会把全部字段取出来,而是专门做了优化,不取值,直接按行累加。

所以最后得出的结果是:count(字段)<count(主键 id)<count(1)≈count(*)。

 

加油吧! 奥利给!

posted @ 2020-03-26 11:09  秋天的风,夏天的雨  阅读(833)  评论(0编辑  收藏  举报