MySQL

洞悉MySQL底层架构与SQL调优本质
帅旋
关注
充电
IT宅站长,技术博主,共享单车手,全网id:arthinking。

从SQL执行原理看调优本质:count

发布于 2020-06-26 | 更新于 2024-02-24

存储引擎的区别

  • MyISAM引擎每张表中存放了一个meta信息,里面包含了row_count属性,内存和文件中各有一份,内存的count变量值通过读取文件中的count值来进行初始化。[1]但是如果带有where条件,还是必须得进行表扫描

  • InnoDB引擎执行count()的时候,需要把数据一行行从引擎里面取出来进行统计。

下面我们介绍InnoDB中的count()。

count中的一致性视图

InnoDB中为何不像MyISAM那样维护一个row_count变量呢?

前面 洞悉MySQL底层架构:游走在缓冲与磁盘之间 一文我们了解到,InnoDB为了实现事务,是需要MVCC支持的。MVCC的关键是一致性视图。一个事务开启瞬间,所有活跃的事务(未提交)构成了一个视图数组,InnoDB就是通过这个视图数组来判断行数据是否需要undo到指定的版本。

如下图,假设执行count的时候,一致性视图得到当前事务能够取到的最大事务ID DATA_TRX_ID=1002,那么行记录中事务ID超过1002都都要通过undo log进行版本回退,最终才能得出最终哪些行记录是当前事务需要统计的:

image-20200607161751139

row1是其他事务新插入的记录,当前事务不应该算进去。所以最终得出,当前事务应该统计row2,row3。

执行count会影响其他页面buffer pool的命中率吗?

我们知道buffer pool中的LRU算法是是经过改进的,默认情况下,旧子列表(old区)占3/8,count加载的页面一直往旧子列表中插入,在旧子列表中淘汰,不会晋升到新子列表中。所以不会影响其他页面buffer pool的命中率。

count(主键)

count(主键)执行流程如下:

  • 执行器请求存储引擎获取数据;
  • 为了保证扫描数据量更少,存储引擎找到最小的那颗索引树获取所有记录,返回记录的id给到server。返回记录之前会进行MVCC及其可见性的判断,只返回当前事务可见的数据;
  • server获取到记录之后,判断id如果不为空,则累加到结果记录中。

image-20200607165008486

count(1)

count(1)与count(主键)执行流程基本一致,区别在于,针对查询出的每一条记录,不会取记录中的值,而是**直接返回一个"1"**用于统计累加。统计了所有的行。

count(字段)

与count(主键)类似,会筛选非空的字段进行统计。如果字段没有添加索引,那么会扫描聚集索引树,导致扫描的数据页会比较多,效率相对慢点

count(*)

count(*)不会取记录的值,与count(1)类似。

执行效率对比:count(字段) < count(主键) < count(1)

References


  1. https://zhuanlan.zhihu.com/p/54378839. Retrieved from https://zhuanlan.zhihu.com/p/54378839 ↩︎

本文作者: 帅旋

本文链接: https://www.itzhai.com/columns/mysql/sql/count.html

版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

×
IT宅

关注公众号及时获取网站内容更新。