为了账号安全,请及时绑定邮箱和手机立即绑定

MySQL读取数据时发生了什么?数据读取过程分析[图]

上一篇我们说到B+树拼接一己之力杀出重围,最后成为了InnoDB和MyISAM这两种存储引擎的索引实现。我们都知道索引心里是有B+树的,他知道自己不可能全部存储在内存中,他一般是以「索引文件的形式存储的磁盘上」。那么MySQL读取数据时都发生了什么呢?这得从内存开始说起。

IRAM与ROM

ROM,Read-OnlyMemory:只读储存器,可以理解为电脑的硬盘上存放操作系统的软件,手机的内置储存上存放操作系统的软件,单片机的Flash上存放操作系统的软件。总之就是用来存储操作系统的软件。

RAM,Random-AccessMemory:随机储存器,可以理解为电脑的内存条。用于存放动态数据,也叫运行内存。系统运行的时候,需要把操作系统从ROM中读取出来,放在RAM中运行。

CPU要运行程序需要从ROM调取,但ROM又有距离,所以需要用RAM来做一个连接。

https://img1.sycdn.imooc.com//5f6e03e50001b49911870826.jpg

I主存存储原理

RAM主要的作用就是存储代码和数据供CPU在需要的时候调用,但是这些数据并不是像用碗盛饭那么简单,我们是需要知道数据的特定位置信息。他更像是图书馆中用有格子的书架存放书籍一样,不但要放进去还要能够在需要的时候准确的调用出来,虽然都是书但是每本书是不同的。对于RAM等存储器来说也是一样的,虽然存储的都是代表0和1的代码,但是不同的组合就是不同的数据。

抽象地看,主存是一系列的存储单元组成的矩阵,每个存储单元存储固定大小的数据。每个存储单元有唯一的地址,现代主存的编址规则比较复杂,这里将其简化成一个二维地址:通过一个行地址和一个列地址可以唯一定位到一个存储单元。

I离主存读写工程

当系统需要读取主存时,则将地址信号放到地址总线上传给主存,主存读到地址信号后,解析信号并定位到指定存储单元,然后将此存储单元数据放到数据总线上,供其它部件读取。写主存的过程类似,系统将要写入单元地址和数据分别放在地址总线和数据总线上,主存读取两个总线的内容,做相应的写操作。

所以,主存存取的时间仅与存取次数呈线性关系,因为不存在机械操作,两次存取的数据的“距离”不会对时间有任何影响,例如,先取A0再取A3和先取B0再取C3的时间消耗是一样的。

I磁盘的构成

如果我们将硬盘拆开,可以发现里面存在多张磁盘和多个读写磁头,加入一张磁盘有8张磁盘,就会有16个盘面和16个读写磁头了,所有的盘面构成了磁盘组合。

磁盘组合由一个或多个圆盘组成,他们围绕一根中心主轴旋转,圆盘的上下表面涂抹了一层磁性材料,二进制位被存储在这些磁性材料上。其中,0和1在磁材料中表现位不同的模式。

盘片被划分成一系列同心环,圆心是盘片中心,每个同心环叫做一个「磁道」,所有半径相同的磁道组成一个柱面。磁道被沿半径线划分成一个个小的段,每个段叫做一个「扇区」,每个扇区是磁盘的最小存储单元。为了简单起见,我们下面假设磁盘只有一个盘片和一个磁头。

I随机读取

一般来说,主存和磁盘以页为单位交换数据。在硬件及操作系统中,我们往往将主存和磁盘存储区分割为连续的大小相等的块。每个存储块称为一页(在许多操作系统中,页的大小通常为4k或者8k)。

I随机读取过程

在交换数据时,系统会将数据逻辑地址传给磁盘,磁盘的控制电路按照寻址逻辑将逻辑地址翻译成物理地址,即确定要读的数据在哪个磁道,哪个扇区。为了读取这个扇区的数据,需要将磁头放到这个扇区上方。

I随机读取性能瓶颈

随机读取主要与性能瓶颈这三个指标有关:

1.磁头需要移动对准相应磁道的时间即寻道时间

2.磁盘旋转到指定磁道区域,即旋转延迟

3.从磁盘读出或将数据写入磁盘的时间,即传输时间。

一般来说,主流磁盘寻道时间一般在5ms以下;旋转延迟也就是转速的一般(对于圆形来说,最多走一半就能到对应区域),对于7200转的磁盘,旋转延迟应该在7200/3600/2=4.17ms。传输时间可以忽略不计,所以一次磁盘IO耗时应该在9ms以内。

其实9ms的随机读取其实已经是一个灾难,比如一台常规的500-MIPS的机器每秒可以执行5亿条指令,也就是说一次随机读取的时间,机器可以执行5百万条指令,这个量级对比是惊人的。书笔记作文网https://www.yuananren.com而且,对于一个百万级数据库查询的话,所花费的时间已经达到了9s,这个数据对于用户来说其实是一个难以容忍的数字了。

I局部性原理

考虑到随机读取是高昂的消耗这个客观存在的事实,我们计算机系统利用了局部性原理对磁盘进行顺序读取。

日常生活中,我们都知道很多东西的分布都不是平均的,我们更常见的概率分布其实是正态分布。一个很形象的例子就是,大学中经常旷课的同学,他的朋友也会经常旷课,他们形成了一个旷课圈。

磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。所以当一个数据被用到时,其附近的数据也通常会马上被使用。程序运行期间所需要的数据通常比较集中。这就是我们的局部性原理。

I顺序读取

磁盘顺序读取不需要寻道时间,只需很少的旋转时间。所以,我们对于具有局部性的程序来说,预读可以提高I/O效率。

I顺序读取过程

当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。也就是我们读取一页内的数据时候,实际上才发生了一次IO。

如果我们需要将多个页读取到缓冲池中,并按顺序处理它们,此时读取的速度变的很快,此时读取每个页所花费的时间大概为0.1ms左右,这个时间消耗对随机IO有很大的优势。

I顺序读取的条件

全表扫描

全索引扫描

索引片扫描

通过聚簇索引扫描表行

I离顺序读取的优势

节省开销。读取多页意味着平均读取每页性能增加。

预读。由于数据库引擎知道需要读取哪些页,所有可以在页被真正请求之前就提前将其读取进来。

IMySQL数据读取

MySQL数据的读取并不是简单直接将内存与磁盘进行数据交换,而是使用缓冲池最小化磁盘活动。

每一个缓冲池都足够大,大到可以存放许多页,可能是成千上万的页。内存缓冲池和磁盘缓冲池遵循局部性原理,尽力确保经常使用的数据被保存于池中,以避免一些不必要的磁盘读。

根据主存存储原理,我们可以很快在缓冲池找到一个索引或者表页。如果在缓冲池中,没有找到数据,会从磁盘服务器的缓冲区里面去读取。磁盘缓存池读取成本大概会在1ms左右。如果磁盘服务器的缓冲池中依然没有找到数据,此时就必须要从磁盘读取了。如果满足顺序读取的条件,那么就会尽快地顺序读取。如果不满足,那么就会可怕的随机读取。

I总结

本文主要阐述了MySQL数据读取的流程。认识到因为自己的小任性,需要查询一个值,MySQL这个暖男居然鞍前马后干了这么多事情。甚至开始心疼软件工程师,软件工程师们想尽各种办法来做优化,性能提升却是有限的。而硬件上的稍微有优化,性能提升却是飞跃的。比如顺序读取1MB数据,机械硬盘是20ms,SSD只需要1ms。更改硬盘达到速度的提升可能让福报程序员可以掉更少的头发,获得更多的休息。


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消