深入理解顺序io和随机io(全网最详细篇)

news2024/9/22 23:18:49

MySql系列整体栏目


内容链接地址
【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025
【二】深入理解mysql索引优化以及explain关键字https://blog.csdn.net/zhenghuishengq/article/details/124552080
【三】深入理解mysql的索引分类,覆盖索引(失效),回表,MRRhttps://blog.csdn.net/zhenghuishengq/article/details/128273593
【四】深入理解mysql事务本质https://blog.csdn.net/zhenghuishengq/article/details/127753772
【五】深入理解mvcc机制https://blog.csdn.net/zhenghuishengq/article/details/127889365
【六】深入理解mysql的内核查询成本计算https://blog.csdn.net/zhenghuishengq/article/details/128820477
【七】深入理解mysql性能优化以及解决慢查询问题https://blog.csdn.net/zhenghuishengq/article/details/128854433
【八】深入理解innodb和buffer pool底层结构和原理https://blog.csdn.net/zhenghuishengq/article/details/128993871
【九】深入理解mysql执行的底层机制https://blog.csdn.net/zhenghuishengq/article/details/128100377
【十】深入理解mysql集群的高可用机制https://blog.csdn.net/zhenghuishengq/article/details/126239652
【彩蛋篇】深入理解顺序io和随机iohttps://blog.csdn.net/zhenghuishengq/article/details/129080088

深入理解顺序io和随机io

  • 一,顺序io和随机io
    • 1,机械硬盘的组成
    • 2,磁盘
    • 3,顺序io和随机io
    • 4,预读
    • 5,innodb存储引擎的顺序io

一,顺序io和随机io

1,机械硬盘的组成

在研究顺序io和随机io之前,先了解一下这个机械磁盘,一个机械磁盘的官方图片如下,其主要由主轴,磁头,磁盘,磁头臂等等部分组成。接下来谈一下各个组件的作用。
在这里插入图片描述

磁盘 :数据是存储在磁盘的盘片上面的,磁盘由多个盘片组成,主要是通过盘片的转动来让磁头读取数据的。

磁头:在需要读取数据的时候,磁头就会移到这个盘片上面读取数据,如果出现断电的情况,那么磁头就会从盘片上移开移回到原来的位置,磁头和盘片之间的距离非常的小。

磁头臂:磁头臂主要是控制这个磁头进行一个移到和旋转,让磁头去读取内容和归位。由于多个磁头都绑定在一个磁头臂上面,因此多个磁头都是一起移动的,其距离,方向等都是一模一样的。

主轴:通过主轴的转动来实现这个盘片的移动。

2,磁盘

在磁盘内部,又对 磁盘上的每个盘片 进行了更加精确的细分。如下图,每个盘片上面都由磁道和扇区组成,磁道是由一个一个的小圆环组成,每一个圆圈又进行了一个更小的划分,被称为扇区,如下面所示,一个磁道由八个扇区组成。

现在市面上流行的基本上是这种,一个磁盘八个扇区,每个扇区存储512kb数据,并且在磁盘中也是以页为单位存储数据,和innodb的页不同,他是八个扇区为一个页,即一页大小为4kb,在读取某一个扇区的内容时,会将一页的数据全部给读取出来,因此一般一次磁盘io出来的数据就是4kb。如innodb存储引擎,在存储数据时,innodb中的页就是16kb的,因此存满一页数据需要四次的磁盘io。
在这里插入图片描述

又由于一个磁盘上面存在多个盘片,而多个磁头又是固定在磁盘臂上面的,那么多个盘片就会形成如下图所示,形成一个圆柱体,多个盘片对应位置的磁道就形成了一个柱面。如下面的黄色部分,四个盘面都有这个黄色的磁道,这样黄色部分的四个磁道就形成了一个圆柱体状的柱面。因此要确定数据在哪个位置,首先得确定柱面号,即是属于黄色部分还是蓝色部分,先将这个圆柱体状的柱面找到,再确定盘片号,即数据是在哪个盘片的盘面上,最后确定扇区

在这里插入图片描述

在确定数据的位置之后,就需要开始移动这个磁头,将磁头定位到具体磁道,如上图的最上面的那个磁头,在0号盘面上,其先定位到黄色部分的那个磁道;在定位到具体的磁道之后,就通过这个主轴将盘片转动,将扇区转动到磁头指向的地方,这样就可以定位到具体的扇区了,那么就可以将扇区的全部内容读取出。

在整个读取数据的过程中,主要分为三个时间:寻找磁道和盘面时间 + 盘面旋转时间 + 读取和传输数据的时间 ,就是一次磁盘的io读取数据的时间,大概在 9 - 10ms 左右。寻找磁道和盘面需要移动磁头臂,而盘面旋转找扇区的时间可以忽略不,因为现在的设备都是 5600r/s,7200r/s,转一圈的需要的时间微乎其微;从磁盘读取数据由于是按扇区直接读取,其时间也可以忽略不计;那么这个寻找磁道和盘面,就需要花费最多的时间了,因为需要来回移动磁头,这是一个很重的物理量操作。

因此这就解释了为什么要按扇区读取数据了,因为定位到具体的位置花费的时间长,所以直接读取整个扇区的数据,省的将磁头移来移去,并且在这种读取磁盘数据时,会顺便的将周围的扇区里面的值也读取出来,也是为了解决移动磁头很耗时的问题,这种方式被称为预读,如读取mysql数据,会通过预读的方式将周围的数据读取出来。

因此,磁盘读取数据的最小单位就是扇区。即使只需要读取里面的一个字节,也需要将整个扇区的内容全部读出

3,顺序io和随机io

在得知磁盘的底层运行原理之后,这里就知道了为啥随机io要比顺序io慢的原因了。由于在磁盘中读取数据时,盘面旋转的时间和读取数据的时间可以忽略不计,主要是这个寻找磁道和盘面要花较多的时间,即移动磁头需要花费大量的时间,那么主要是在这个地方拉开时间差的。
在这里插入图片描述

举个例子,依旧选择上面的黄色部分的磁道,那么拿顺序io来说,由于顺序io是有序的,那么如果数据只分布在一个磁道里面,那么这些数据都是连续有序的,那么读取这一个磁道的数据,顺序io和随机io可能都差不多,因为磁头不需要移动,随机io产生的时间可能比顺序io产生的时间多就是磁道旋转的次数,可能随机会多转几圈

但是,如果数据随机分布在整个盘片上,那就不一样了。依旧选择黄色部分和最外面的蓝色部分两个磁道,假设数据随机分布在两个磁道上面,旋转和读取的时间忽略不计,那么顺序io只需要磁头移动两次;而随机io就不一样了,上面八个扇区,如果第一次在这个磁道,第二次又去了那个磁道…,那么随机io的磁头移动的次数是2到16次,这样顺序io是小于或者远小于随机io的时间的

照此类推,假设要读取的数据分布在整个磁盘的随机位置,如上图假设10个磁道,那么顺序io的磁头只需要移动10次,但是随机io需要移动 10 到 80次,这样才能将数据全部读完,由于移动时间是整个时间最耗时的,因此随机io在最坏的情况下,其消耗的时间远远大于顺序io。而且上面只讨论在一个盘面,如果是在多个盘面的情况下,其随机IO的最坏时间更要远远的超出这个顺序IO的时间了。

顺序io的效率是随机io的40-400倍,当然除了顺序读,顺序写也是随机写的10-100倍,其原理一样,主要是寻道时间比较长。

4,预读

磁盘在读取数据时,直接将一个扇区的数据读取出,这个行为被称为预读。不仅仅是在磁盘中,在cpu,内存,甚至在整个计算机中,预读的使用都比较频繁。和计算机中的局部性原理相关,这个原理也是在磁盘,内存,ssd盘中都会使用到这个原理。即一个数据在被读取时,其附近的的数据也通常会被使用。

在数据预读的时候,可能并不只读一个扇区,而是读连着的几个扇区,数据预读的单位是以页为单位的,一页的大小大概在4kb左右,所以操作系统在处理磁盘的数据的时候,是以页为单位将数据载入到内存中的。

看一段代码,如下

/**
 * @Author: zhenghuisheng
 * @Date: 2023/02/13 02:03
 */
public class ArrayTest {
    public static void main(String[] args) {
        int k = 10000 , p = 10000 , sum1 = 0 , sum2 = 0;
        //定义一个二维数组
        int data[][] = new int[k][p];
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < p; j++) {
                data[i][j] = i % 10;
            }
        }
        long firstTime = System.currentTimeMillis();
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < p; j++) {
                //按行操作
                sum1 += data[i][j];
            }
        }
        System.out.println("按行操作消耗的时间 :"+(System.currentTimeMillis() - firstTime));

        long secondTime = System.currentTimeMillis();
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < p; j++) {
                //按列操作
                sum2 += data[j][i];
            }
        }
        System.out.println("按列操作消耗的时间 :"+(System.currentTimeMillis()-secondTime));
    }
}

其运行结果如下,其按列消耗的时间大概是按行消耗消耗的时间的30倍。而且这不是最坏的情况,因为随机io的时间是不确定的,但是肯定会大于顺序io。

按行消耗的时间 : 118ms
按列消耗的时间 : 3022ms

一个二维数组,其实就是由多个一维数组组成。而在一维数组中,其内存地址是一块连续的空间,那么在按行读取数据的情况下,这个二维数组也是一块连续的地址。如下面这个数组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kVmQNI8b-1676601004655)(img/1670901071504.png)]

其按行读取数据的过程如下图,其就是一个内存的顺序读取数据的过程。其值从1009,一直到1020都是排好序的,因此在数组中按行读就是一个顺序读取数据的一个过程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OxsFcTN8-1676601004656)(img/1670902036595.png)]

按列读取数据就不一样了,由于按行是顺序的连续的地址,那么按列肯定就是不连续的,随机的地址了,因此按列读取数据就是一种类似于内存的随机读取数据的过程。如下图,在读取到第一个数据后,读取第二个数据就要开始找位置了,我这里数据少,是在第5个位置,但是如果像上面的代码是10000 x 10000的情况下,那么就需要找找到第10001个数据,才是第二个数据,第三个数据在20001个位置,以此类推…。这样每个数据都需要跳来跳去的在这个连续的空间中寻找,这样查询时间就占很大一部分了。

在这里插入图片描述

这就解释了,为什么在计算机底层中,那么倾向于往顺序io的方向优化了。

5,innodb存储引擎的顺序io

首先磁盘通过预读的方式读取数据,有可能不仅仅是加载磁盘中一页数据,也可能是加载好几页的数据(磁盘中一页数据为8个扇区的数据,每个扇区512kb,那么一页就是4kb的数据)。所以在innodb的存储引擎中,也可能直接通过预读的方式,将innodb的一页甚至多页数据给直接的全部读取出来,innodb一页数据是16kb,和这个磁盘中的数据页本质不同。

并且在innodb的存储引擎中,其索引的本质就是一棵b+树,所有的数据都是在聚簇索引上面的,因此其内部是排好序的,如果是顺序io,那么一次就可以将当前页的数据和周围页的数据通过预读的方式给读取出来,因此B+树的有序性,也非常适应这个顺序读写,假设b+树不是顺序的,那么要读取相邻的顺序,那么就可能需要不断的来回移动这个磁头来定位,这样也是需要花费大量的时间的,所以mysql底层也是选择有序的b+树来作为索引,也是更符合顺序读写的原则。

因此在mysql内部进行优化的时候,都是让数据进行顺序读写的,而不是随机读写的,如mysql对顺序读写有这些体现点:如MRR机制,对回表的id进行一个排序,然后进行一个顺序的查找,从而减少回表时的随机读写;还有redolog的日志,也是顺序的写,等等。其目的就是为了减少寻找磁道和扇区的时间,减少磁头移动的时间,因为磁头移动是一个机械运动,是一个重操作,需要花费大量的时间。

除了这个mysql内部对顺序读写有着一些相关的优化,还有如kafka等内部也是使用了这个顺序io的。

这里主要是了解磁盘中的随机读和顺序读,当然内存,ssd盘等都有顺序io和随机io,虽然内部实现方式和磁盘不大一样,但是顺序io的时间都是小于或者远小于随机io的时间的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/351551.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

汽车如何实现制动

汽车如何实现制动 汽车如何实现制动 难点答疑&#xff1a;汽车刹车时&#xff0c;四个车轮是如何制动的&#xff1f;制动机理是什么&#xff1f; 第一步&#xff1a;驾驶员踩下制动踏板&#xff0c;推动制动主缸 第二步&#xff1a;制动主缸将制动液的压力通过制动管道传递到四…

数据结构代码总结(C语言实现)

目录如何应对数据结构的代码题&#xff1f;采取的学习流程①首先对C语言的语法的熟悉②学习掌握基本代码的写法&#xff0c;做到熟练2.1插入排序2.2快速排序2.3二分查找2.4树的遍历③跟着网上视频开始熟悉对一些问题的解答④结合真题的代码&#xff0c;寻找其中的结题规律如何应…

CasEE: 一种用于重叠事件抽取的级联解码联合学习框架 论文解读

CasEE: A Joint Learning Framework with Cascade Decoding for Overlapping Event Extraction (用于重叠事件抽取的级联解码联合学习框架) 论文&#xff1a;CasEE: A Joint Learning Framework with Cascade Decoding for Overlapping Event Extraction (aclanthology.org) 代…

通俗易懂理解三次握手、四次挥手(TCP)

文章目录1、通俗语言理解1.1 三次握手1.2 四次挥手2、进一步理解三次握手和四次挥手2.1 三次握手2.2 四次挥手1、通俗语言理解 1.1 三次握手 C:客户端 S&#xff1a;服务器端 第一次握手&#xff1a; C&#xff1a;在吗&#xff1f;我要和你建立连接。 第二次握手&#xff…

设计模式之门面模式与装饰器模式详解和应用

目录1 门面模式定义1.1 门面模式的应用场景1.2 门面模式的通用写法1.3 门面模式业务场景实例1.4 门面模式在源码中的应用1.5 门面模式的优缺点2 装饰器模式2.1 装饰器模式定义2.2 装饰器模式的应用场景2.3 装饰器模式在源码中的应用2.4 装饰器模式和代理模式对比2.5 装饰器模式…

git命令篇(持续更新中)

首先介绍这个网页&#xff1a;https://learngitbranching.js.org/?localezh_CN --提交命令 git commit --创建分支 git branch <分支名> --切换分支 git checkout <分支名> --合并分支 (合并到主分支去&#xff0c;把我合并到谁的身上去) 自己写的分支合并到主线…

Unity—游戏设计模式+GC

每日一句&#xff1a;"少年一贯快马扬帆 道阻且长不转弯 要盛大要绚烂要哗然 要用理想的泰坦尼克去撞现实的冰川 要当烧赤壁的风而非借箭的草船 要为一片海就肯翻万山。" 目录 状态模式&#xff1a; 外观模式 组合模式&#xff0c; 单例模式 命令模式 观察者模…

FPGA开发软件(vivado + modelsim)环境搭建(附详细安装步骤+软件下载)

本文详细介绍了vivado软件和modelsim软件的安装&#xff0c;以及vivado中配置modelsim仿真设置&#xff0c;每一步都加文字说明和图片。一、软件安装包下载1、vivado vivado版本很多&#xff0c;目前最新的已更新到vivado2022.2&#xff0c;版本越高&#xff0c;安装包越大&…

90后阿里P7技术专家晒出工资单:狠补了这个,真香...

最近一哥们跟我聊天装逼&#xff0c;说他最近从阿里跳槽了&#xff0c;我问他跳出来拿了多少&#xff1f;哥们表示很得意&#xff0c;说跳槽到新公司一个月后发了工资&#xff0c;月入5万多&#xff0c;表示很满足&#xff01;这样的高薪资着实让人羡慕&#xff0c;我猜这是税后…

全局快门和卷帘快门(Global shutter and Rolling shutter)

全局快门和卷帘快门 “果冻效应”是什么&#xff1f;用相机拍下扇叶&#xff0c;为什么会发生扭曲变形&#xff1f; 相机两种曝光方式的优劣&#xff1a;全局曝光和卷帘曝光 卷帘快门和全局快门的区别 全局曝光和卷帘曝光是常见的相机曝光方式 一般来说&#xff0c;CCD相机是全…

【3D目标检测】Fastpillars-2023论文

论文&#xff1a;fastpillars.pdf https://arxiv.org/abs/2302.02367 作者&#xff1a;东南大学&#xff0c;美团 代码&#xff1a;https://github.com/StiphyJay/FastPillars &#xff08;暂未开源&#xff09; 讲解&#xff1a;https://mp.weixin.qq.com/s/ocNH2QBoD2AeK-…

「JVM 编译优化」javac 编译器源码解读

Java 的编译过程 前端编译: 编译器的前端&#xff0c;将 Java 文件转变成 Class 文件的过程&#xff1b;如 JDK 的 javac、Eclipse JDT 中的增量式编译器 ECJ&#xff1b;即使编译: JIT&#xff0c;Just In Time Compiler&#xff0c;在运行期将字节码转变成本地机器码的过程&…

COSELF 次元秀场伦敦时装周预告 #虚拟时尚

在虚拟世界里的未来服装&#xff0c;能自由变化自己的样貌和服饰。或许未来会作为人类皮肤的第二表征&#xff0c;极大解放人们的精神自由。COSELF 次元秀场 「预告」数字高定系列时间&#xff1a;本月 17 - 21 日地点&#xff1a;当季伦敦时装周「COSELF 次元秀场-数字高定系列…

excel图片技巧:如何为报表配上节日祝福动画

偶尔跳跃一下&#xff0c;改变一下&#xff0c;哪怕被说成是“拍马屁”也行&#xff0c;因为&#xff0c;快乐、传递快乐是一种幸福&#xff0c;是内心本身就有的欲望。提升自己在同事和领导心里的形象只是传递快乐的附加值。圣诞节就快到了&#xff0c;发送报表的时候附带一个…

vue的组件通信

文章目录3. 组件通信3.1 父组件-->子组件3.3组件自定义事件&#xff08;子->父&#xff09;3.4.全部事件总线&#xff08;两代以上&#xff09;3.5消息的订阅与发布3. 组件通信 3.1 父组件–>子组件 <Student name"张三" :age"18"></St…

Java Excel的数据导入导出

引入依赖 <!-- EasyExcel --> <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.7</version> </dependency><!--csv文件操作--> <dependency><groupId>n…

将ChatGPT整合到Word中

引言自ChatGPT出现&#xff0c;各种基于它的软件扩展纷至沓来&#xff0c;目前Word支持ChatGPT的add-in有两款&#xff0c;可以通过:插入->获取加载项->搜索openai查看。其中Ghostwriter从介绍上看功能比较单一&#xff0c;而且软件需要购买&#xff0c;用自己的API-key&…

php5.6.9安装sqlsrv扩展(windows)

报错:Marning: PHP Startup: Unable to load dynamic 1library D:lphpstudy_prolExtensionslphpl(phps.6.9ntslextphp_ pdo_sqlsry 56 nts′找不到指定的模块。in Unknown on line 0 整整搞了一天才终于解决 我用的是phpstudy_pro&#xff08;也就是小皮v8.1版本&#xff09;&…

Twitter多账号想要做到防关联?还是得靠它

接着上一篇Twitter养号攻略的文章&#xff0c;这篇龙哥就来详细讲讲当批量注册和管理Twitter账号时需要怎么防关联。 Twitter作为海外最流行的社交网站之一&#xff0c;它拥有很庞大的用户量&#xff0c;所以很多跨境电商都会通过Twitter来投放广告、推广自己的产品、提高曝光度…

pdf生成为二维码

当今数字时代&#xff0c;人们越来越依赖在线工具来处理各种任务&#xff0c;比如合并、拆分和压缩PDF等。Mai File就是这样一个在线工具&#xff0c;它可以将PDF文件转换成在线链接&#xff0c;方便您和他人轻松地查看和共享文件。 Mai File的使用非常简单&#xff0c;您只需…