深入理解顺序io和随机io(全网最详细篇)
MySql系列整体栏目
| 内容 | 链接地址 |
|---|---|
| 【一】深入理解mysql索引本质 | https://blog.csdn.net/zhenghuishengq/article/details/121027025 |
| 【二】深入理解mysql索引优化以及explain关键字 | https://blog.csdn.net/zhenghuishengq/article/details/124552080 |
| 【三】深入理解mysql的索引分类,覆盖索引(失效),回表,MRR | https://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和随机io | https://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)]](https://img-blog.csdnimg.cn/050086d56c1542979bf0a8b59a66d515.png)
其按行读取数据的过程如下图,其就是一个内存的顺序读取数据的过程。其值从1009,一直到1020都是排好序的,因此在数组中按行读就是一个顺序读取数据的一个过程。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OxsFcTN8-1676601004656)(img/1670902036595.png)]](https://img-blog.csdnimg.cn/e30781cd7482457baace6fbec9a40252.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的时间的。
相关文章:
深入理解顺序io和随机io(全网最详细篇)
MySql系列整体栏目 内容链接地址【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025【二】深入理解mysql索引优化以及explain关键字https://blog.csdn.net/zhenghuishengq/article/details/124552080【三】深入理解mysql的索引分类&a…...
面试准备知识点与总结——(基础篇)
目录Java基础Java面向对象有哪些特征ArrayList和LinkedList有什么区别高并发的集合有哪些问题迭代器的fail-fast和fail-safeArrayList底层扩容机制HashMap面试合集解答设计模式单例设计模式哪些地方体现了单例模式Java基础 Java面向对象有哪些特征 Java面向对象有三大特征&am…...
Linux共享库,静态库与相关系统调用,工具的使用总结
tags: Linux C Syscall 写在前面 总结Unix/Linux操作系统的共享库/静态库部分, 以及一些系统调用. 参考Linux/UNIX系统编程手册41-42章. 测试程序均在Ubuntu下使用cc(gcc-9)运行成功. $ gcc -v Using built-in specs. COLLECT_GCCgcc COLLECT_LTO_WRAPPER/usr/lib/gcc/x86_64…...
「JVM 编译优化」javac 编译器源码解读
Java 的编译过程 前端编译: 编译器的前端,将 Java 文件转变成 Class 文件的过程;如 JDK 的 javac、Eclipse JDT 中的增量式编译器 ECJ;即使编译: JIT,Just In Time Compiler,在运行期将字节码转变成本地机器码的过程&…...
Leetcode DAY 34: K次取反后最大化的数组和 and 加油站 and 分发糖果
1005.K次取反后最大化的数组和 class Solution:def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:nums sorted(nums, key abs, reverse True)for i in range(len(nums)):if nums[i] < 0:nums[i] -nums[i]k - 1else:continueif k 0:return sum(…...
2023美赛A题思路
在线解析 https://kdocs.cn/l/ccNGjN9sGugLkdocs.cn/l/ccNGjN9sGugL A题思路:(具体以题目解决问题顺序为主) 这道题分析植被就行,主要涉及不同植被间的相互作用,有竞争有相互促进,我查了下“植物科学数…...
前端上传文件
前言 以 vue 举例,原生 html css js 现在应该很少有人去写了 一、绘制样式 绘制两个标签,一个 <div></div> ,一个 <input type"file" />; 为 <div></div>添加 css 样式,…...
后台管理系统中选项卡的动态渲染
动态渲染选项卡其中router-link是为了当点击选项卡时跳转到选项卡所在的列表选项卡需要动态渲染,其中active是当选中后激活选中的样式为图标添加点击删除事件在状态机配置tabMenu(为了动态渲染)需要在tabMenu添加:active、title、…...
网络层重点协议之IP协议(IPv4)
网络层的作用就是来路由的选择,规划传输的路径,其中网络层的重点协议就是IP协议。4位版本号版本号的取值只有4和64位首部长度描述了IP报头有多长,报头中有一个选项部分,是变长的,是可有可无的部分,所以IP报…...
CentOS Stream 8配置DNS
1:用CentOS搭建DNS的目的是想解析一台下载服务器,IP地址172.18.0.58,现在是用IP地址方的式访问,想搭建DNS服务器用域名的方式访问。 使用下面的命令查看一下当前系统的Bind版本。 yum info bind 版本是9.11.36.我的CentOS是最小…...
【roLabelImg】windows下旋转框标注软件安装、使用、rolabelimg打包成exe
主要参考: roLabelImg安装、使用、数据格式roLabelImg在Win10系统下打包成exe - 问雪的文章 - 知乎 一、安装 1.1 直接下载exe运行 劝大家直接去下别人编译好的吧,本来是训练模型标记的,结果搞了半天去了解这个软件了,哎~ 我…...
2023美赛F题:绿色经济
文章目录背景要求词汇表背景 国内生产总值(GDP)可以说是最知名且最常用的衡量一个国家经济健康的指标之一。它通常用于确定一个国家的购买力和贷款能力,为国家提出提高GDP的政策和项目提供了动力。GDP “衡量一个国家在一段特定时间内生产的…...
华为OD机试 - 剩余可用字符集 | 备考思路,刷题要点,答疑 【新解法】
最近更新的博客 【新解法】华为OD机试 - 关联子串 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 停车场最大距离 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 任务调度 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试…...
“笨办法”学Python 3 ——练习 40. 模块、类和对象
练习40 模块、类和对象 知识点: 40.1.0 模块就像字典 my_stuff[apple] #my_stuff是字典,访问字典apple键的值 import mystuff mystuff.apple() #mystuff是模块,模块访问函数apple() print(mystuff.tangerine) #模块访问变量tangerine说明P…...
自动驾驶:BEVDet
自动驾驶:BEVDetIntroductionMethodoloData AugmentationNetwork StructureScale-NMS实验Introduction 作者通过现有的算法(LSS)、独特的数据增强方案与新的NMS方案整合了一个BEV框架(BEVDet)。 如下图: …...
vue的组件通信
文章目录3. 组件通信3.1 父组件-->子组件3.3组件自定义事件(子->父)3.4.全部事件总线(两代以上)3.5消息的订阅与发布3. 组件通信 3.1 父组件–>子组件 <Student name"张三" :age"18"></St…...
Typescript的定义及使用优势
编程语言的类型: 动态类型语言 (Dynamically Typed Language)静态类型语言 (Statically Typed Language) 两种语言的含义及区别: 比如JS、python就是动态类型语言,什么是动态类型语言,通俗的讲࿰…...
正则验证:手机号码验证
<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></title> </head> <body> 手机号码<input type"text" id"phone"> <span…...
视频融合 flv流格式对接(上)
FLV 是FLASH VIDEO的简称,FLV流媒体格式是随着Flash MX的推出发展而来的视频格式。由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大…...
提问:影视剪辑解说都是怎样配音的,软件合成还是自己配音?
“影视剪辑解说都是怎样配音的,软件合成还是自己配音?”这是一个很好的问题并且困扰着很多人,因为不知道该如何选择。究竟应该使用软件来完成配音工作呢?还是自己动手配音呢?这是一个很难回答的问题。如果你问我的话,…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...
【技巧】dify前端源代码修改第一弹-增加tab页
回到目录 【技巧】dify前端源代码修改第一弹-增加tab页 尝试修改dify的前端源代码,在知识库增加一个tab页"HELLO WORLD",完成后的效果如下 [gif01] 1. 前端代码进入调试模式 参考 【部署】win10的wsl环境下启动dify的web前端服务 启动调试…...
SpringCloud优势
目录 完善的微服务支持 高可用性和容错性 灵活的配置管理 强大的服务网关 分布式追踪能力 丰富的社区生态 易于与其他技术栈集成 完善的微服务支持 Spring Cloud 提供了一整套工具和组件来支持微服务架构的开发,包括服务注册与发现、负载均衡、断路器、配置管理等功能…...
