深入MySQL查询过程底层原理,我找到了MySQL查询慢的根本原因!

2023-11-18

V-xin:ruyuanhadeng获得600+页原创精品文章汇总PDF

前言

接上一节,那么,一次查询的全过程是什么样的呢?

这个时候,我们通过各种百度和Google,然后加上自己的理解,终于搞明白了MySQL一次查询的全过程了。

首先,用户想要查询订单数据时,会先发送一个查询请求,如下图所示:

图片

可以看到,当用户发送查询请求时,因为外卖订单项目是部署在Tomcat中的,Tomcat中的线程首先就会接收到用户的请求,然后把请求交给外卖订单项目。

而外卖订单项目,会根据代码去数据库中查询订单的数据,不管是使用原生的JDBC、还是Mybatis、Hibernate等框架,其实底层都是先获取一个JDBC连接

通过JDBC连接,我们才可以和数据库建立连接,然后通过JDBC的连接,到MYSQL数据库中执行sql语句。

我们来看一下,在MYSQL数据库中是如何执行一个sql语句的,如下图:

图片

JDBC连接是负责和MYSQL通信的,会把sql语句发给MYSQL执行,可以看到MYSQL中,也会有线程获取到JDBC连接中的sql语句,然后去执行。

  • 线程会把sql语句交给MYSQL中的sql接口,sql接口会转发给sql解析器去解析,比如,sql解析器会把一条sql语句中的表名称、WHERE关键字后面的查询条件、以及具体查询哪些字段等信息都解析出来,然后把解析好的信息交给查询优化器处理。
  • 查询优化器会根据sql解析器解析好的sql语句信息,选择一个效率最高的处理方案,来作为执行sql语句的执行计划,然后转交给执行器去执行。
  • 而执行器会调用MYSQL的存储引擎,这里我们用InnoDB存储引擎举例,InnoDB存储引擎中的接口就会来执行sql语句,如下图:

图片

可以看到,MYSQL InnoDB存储引擎中,有一块内存区域叫做Buffer Pool,也叫做缓冲池,一般情况,MYSQL的数据都存放在磁盘中,如果你去查询数据,数据就会从磁盘加载到MYSQL内存中,也就是放在缓冲池Buffer Pool中

而Buffer Pool,如果我们要再细分一下的话,可以看到是由多个chunk组成的,每个chunk大概占128MB内存的大小,每个chunk中都有多个缓存页,每个缓存页的大小是16kb,缓存页就是用来存放加载到内存的数据的

每个缓存页都有个对应的描述数据块,可以把描述数据理解为缓存页的一个指针,通过描述数据就可以找到对应的缓存页。

这个时候,当InnoDB存储引擎执行sql语句查询数据时,首先,得要从磁盘中加载数据,如下图:

图片

这里的表空间呢,指的是独立表空间,在MySQL中,表空间分为2种,分别是共享表空间和独立表空间,不过在MySQL 5.6.6及后续版本默认使用的是独立表空间,说白了就是一个独立表空间在磁盘中会单独对应一个表空间文件,而一个表空间文件存放着MYSQL数据库中一张表的数据。

在表空间中有很多数据区组,每个数据区组中包含256个数据区,而每个数据区中又包含64个数据页,因为每个数据页的大小默认是16KB,所以也就是说一个数据区的大小是1MB。

从磁盘加载数据到MYSQL内存中,其实就是通过磁盘IO的方式,把数据页中的数据加载到缓冲池Buffer Pool中的缓存页中,然后通过InnoDB存储引擎和sql接口,一步步返回给用户。

那么,在查询的整个流程中,哪个环节最容易拖后腿呢?答案就是磁盘IO,也就是将磁盘中的数据页数据读取到Buffer Pool的缓存页这个过程。

那么,磁盘IO为什么会拖后腿呢?磁盘IO的过程大概是什么样子的呢?接下来,就很有必要来看下这一块内容了。


查询慢深层次原因揭秘:磁盘IO的过程

先来看下磁盘的物理结构,如下图:

图片

磁盘内部的组成部分,主要为主轴、磁盘盘片、读写磁头、传动轴和传动手臂,其中数据就是存放在磁盘盘片上的,磁盘盘片被划分为了无数个小扇区,每个扇区中都有很多半径不同的环形磁道,不同的磁道中存放着不同的数据。

在实际读写数据时,主轴会让磁盘盘片转动,然后再通过传动手臂的伸展,让读写磁头在磁盘扇区的磁道上读取和写入数据,一次磁盘IO花费的时间,主要由寻道时间、旋转延迟和数据传输时间三部分构成,接下来,我们分别来看下这三部分的耗时情况。

1 寻道时间

刚才我们知道了,磁盘盘片表面上被分为了无数小扇区,每个扇区中都有很多半径不同的磁道,不同的磁道上放着不同的数据。

而寻道时间,指的是将读写磁头移动到正确半径的磁道上所需要的时间,寻道时间越短,磁盘IO操作越快,目前磁盘的平均寻道时间,一般在3~15ms,主流磁盘一般在5ms以下。

2 旋转延迟

寻道结束后,还需要读写磁头旋转到这个磁道的正确位置上才能读写数据,而旋转延迟,指的是从寻道时间结束开始,到读写磁头旋转到磁道正确位置的这段时间间隔。

但是,我们一般将磁盘旋转周期值的一半,作为旋转延迟的近似值;常见的磁盘转速有5400转和7200转,表示每分钟能转5400和7200圈。

比如,我们以7200转举例,也就是说1秒钟能转120圈,磁盘的旋转周期就是 1/120 秒,所以,旋转延迟的近似值为 1/120/2 = 4.17ms。

3 数据传输时间

传输时间,指的是将数据从磁盘盘片读出或写入的时间,一般在零点几毫秒,相对于前两个时间几乎可以忽略不计,这样来看访问一次磁盘即一次磁盘IO的时间,约等于 5ms + 4.17ms = 9ms。


磁盘的顺序读写和随机读写

另外,磁盘的数据读写,分为随机读写和顺序读写这两种,这两种读写数据的方式,与读写磁头读写数据的方式有关。

顺序读写,顾名思义就是读写磁头从磁盘中的一个位置,按照顺序依次读写磁盘盘片中的数据,速度还是挺快的,比如像MYSQL的redo log日志、binglog日志这些日志信息,比如,顺序写数据时,会相应在一个大日志文件末尾,按照顺序添加日志信息。

随机读写时,读写磁头则会在磁盘盘片中,随机切换到不同半径的磁道上读写数据,频繁切换磁道的这个过程,是非常耗时的。

所以,随机读写的速度相比于顺序读写来说,是会慢很多的,而MYSQL从磁盘中读写数据,正好是比较耗时的随机读写。

正是因为从MYSQL中查询数据,往往要发生多次耗时的随机IO,所以,我们对于一些对查询效率要求较高的数据,一般都会选择固态硬盘来存放。

固态硬盘的工作原理,简单来说就是通过电子的移动来实现数据的读写,相比于磁盘这种物理机械的运作方式,速度是快很多的,但是固态硬盘是比较贵的,基于成本考虑,一般公司大部分机器还是会选择普通机械磁盘的。


磁盘IO到底会有多慢呢?

我们回到刚才,已经知道磁盘IO的工作原理,我们也简单计算了一下,一次磁盘IO大概是9ms的样子,看上去还可以,但是9ms已经非常慢了,那到底有多慢呢,我们可以和内存的速度对比一下。

一般一次内存随机读取的速度,大概在100ns以内,而 1ms = 1000000ns,可以看到,一次磁盘IO耗时是毫秒级的,而内存是纳秒级的。

9ms = 9 * 1000000 ns / 100 ns = 90000,说白了磁盘的速度比内存慢 9万倍左右,那为什么从内存读写数据会那么快呢,简单来说,内存其实是被CPU控制的,而CPU的时钟频率的速度相比于磁盘机械运转速度,速度可以说是非常快了。

当用户发起一次查询请求,一次磁盘IO一般是搞不定的,具体发生磁盘IO的次数,还得要取决于B+树的高度和当时使用索引的情况。

极端情况下,比如没用到索引,一次查询可能会发生100多次磁盘IO,这时,磁盘IO所需的总时间大概是 9ms * 100 = 900ms,也就是0.9秒,这就差不多到秒级别了。

随着数据的快速增长,比如达到了好几亿的数据量,那需要的磁盘IO次数会大幅增加,那这个时候,一次查询所需要的时间,就会达到好几秒。


用户查询请求慢的根本原因

现在,我们知道用户查询请求慢的根本原因了吗?

其实说白了,就是随着数据表中的数据量,变得越来越大,导致磁盘IO发生的次数也相应变多了,如果我们能把磁盘IO的次数降到常数级别,那么查询速度是非常快的,所以,后边的优化都是以降低磁盘IO次数为目标。

V-xin:ruyuanhadeng获得600+页原创精品文章汇总PDF

另外推荐儒猿课堂的1元系列课程给您,欢迎加入一起学习~

互联网Java工程师面试突击课(1元专享)

SpringCloudAlibaba零基础入门到项目实战(1元专享)

亿级流量下的电商详情页系统实战项目(1元专享)

Kafka消息中间件内核源码精讲(1元专享)

12个实战案例带你玩转Java并发编程(1元专享)

Elasticsearch零基础入门到精通(1元专享)

基于Java手写分布式中间件系统实战(1元专享)

基于ShardingSphere的分库分表实战课(1元专享)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入MySQL查询过程底层原理,我找到了MySQL查询慢的根本原因! 的相关文章

  • 将IP保存到数据库中

    当用户登录时 我想将他们的 IP 保存在数据库中 我该怎么做呢 MySQL 字段最适合使用哪种类型 获取IP的PHP代码是什么样的 我正在考虑将其用作登录 会话内容的额外安全功能 我正在考虑使用用户现在拥有的 IP 检查用户从数据库登录的
  • 如何测试 JUnit 测试的 Comparator?

    我需要测试 Compare 方法 但我对如何测试感到困惑 我可以看看该怎么做吗 public class MemberComparator implements Comparator
  • JNI 不满意链接错误

    我想创建一个简单的 JNI 层 我使用Visual studio 2008创建了一个dll Win 32控制台应用程序项目类型 带有DLL作为选项 当我调用本机方法时 出现此异常 Exception occurred during even
  • 如何在 Java 中禁用 System.out 以提高速度

    我正在用 Java 编写一个模拟重力的程序 其中有一堆日志语句 到 System out 我的程序运行速度非常慢 我认为日志记录可能是部分原因 有什么方法可以禁用 System out 以便我的程序在打印时不会变慢 或者我是否必须手动检查并
  • 当分配给变量时,我可以以某种方式重用 Gremlin GraphTraversals 代码吗?

    我有看起来像这样的 GraphTraversals attrGroup GraphTraversal
  • jdbc4.MySQLSyntaxErrorException:数据库中不存在表

    我正在使用 SpringBoot 开发一个网络应用程序 这是我的application properties文件来指定访问数据库的凭据 spring datasource driverClassName com mysql jdbc Dri
  • OnClick 事件中的 finish() 如何工作?

    我有一个Activity一键退出Activity 通过layout xml我必须设置OnClick事件至cmd exit调用 this finish 效果很好 public void cmd exit View editLayout thi
  • 无法理解 Java 地图条目集

    我正在看一个 java 刽子手游戏 https github com leleah EvilHangman blob master EvilHangman java https github com leleah EvilHangman b
  • 检查 Android 手机上的方向

    如何查看Android手机是横屏还是竖屏 当前配置用于确定要检索的资源 可从资源中获取Configuration object getResources getConfiguration orientation 您可以通过查看其值来检查方向
  • 归并排序中的递归:两次递归调用

    private void mergesort int low int high line 1 if low lt high line 2 int middle low high 2 line 3 mergesort low middle l
  • 制作java包

    我的 Java 类组织变得有点混乱 所以我要回顾一下我在 Java 学习中跳过的东西 类路径 我无法安静地将心爱的类编译到我为它们创建的包中 这是我的文件夹层次结构 com david Greet java greeter SayHello
  • 将多模块 Maven 项目导入 Eclipse 时出现问题 (STS 2.5.2)

    我刚刚花了最后一个小时查看 Stackoverflow com 上的线程 尝试将 Maven 项目导入到 Spring ToolSuite 2 5 2 中 Maven 项目有多个模块 当我使用 STS 中的 Import 向导导入项目时 所
  • Java中未绑定通配符泛型的用途和要点是什么?

    我不明白未绑定通配符泛型有什么用 具有上限的绑定通配符泛型 stuff for Object item stuff System out println item Since PrintStream println 可以处理所有引用类型 通
  • 使用 SAX 进行 XML 解析 |如何处理特殊字符?

    我们有一个 JAVA 应用程序 可以从 SAP 系统中提取数据 解析数据并呈现给用户 使用 SAP JCo 连接器提取数据 最近我们抛出了一个异常 org xml sax SAXParseException 字符引用 是无效的 XML 字符
  • Windows 上的 Nifi 命令

    在我当前的项目中 我一直在Windows操作系统上使用apache nifi 我已经提取了nifi 0 7 0 bin zip文件输入C 现在 当我跑步时 bin run nifi bat as 管理员我在命令行上看到以下消息 但无法运行
  • Android JNI C 简单追加函数

    我想制作一个简单的函数 返回两个字符串的值 基本上 java public native String getAppendedString String name c jstring Java com example hellojni He
  • 如何配置eclipse以保持这种代码格式?

    以下代码来自 playframework 2 0 的示例 Display the dashboard public static Result index return ok dashboard render Project findInv
  • 查看Jasper报告执行的SQL

    运行 Jasper 报表 其中 SQL 嵌入到报表文件 jrxml 中 时 是否可以看到执行的 SQL 理想情况下 我还想查看替换每个 P 占位符的值 Cheers Don JasperReports 使用 Jakarta Commons
  • MySQL 概念:会话与连接

    我对 MySQL 的概念有点困惑 会话与连接 当谈论连接到 MySQL 时 我们使用连接术语 连接池等 然而在 MySQL 在线文档中 http dev mysql com doc refman 4 1 en server system v
  • 如何修复“sessionFactory”或“hibernateTemplate”是必需的问题

    我正在使用 Spring Boot JPA WEB 和 MYSQL 创建我的 Web 应用程序 它总是说 sessionFactory or hibernateTemplate是必需的 我该如何修复它 我已经尝试过的东西 删除了本地 Mav

随机推荐

  • Java将PDF文件转为Word文档

    Java将PDF文件转为Word文档 一 创建Springboot Maven项目 二 导入依赖信息
  • STL 中元素拷贝和替换相关算法

    copy 头文件 copy 算法定义在头文件 include 中 算法作用 copy 算法作用是把指定范围的迭代器的元素拷贝到指定的区间 代码示例 vector
  • 开机手动启动 MySQL 服务

    1 图形化界面启动 右击 计算机 在快捷菜单中选择 管理 命令 如图所示 打开 计算机管理 对话框 也可以执行 开始 控制面板 管理工具 服务 来启动服务 改成手动模式 每次电脑开机都需要点击启动服务 2 命令行启动 查看服务命令 net
  • APP版本升级后台接口兼容旧版本

    人工智能 零基础入门 http www captainbed net inner 公司开发APP 经常会有版本升级的情况 因此会出现新版本如何兼容旧版本的问题 iOS和android 不断有新的版本开发 很多服务端开发都是在以前接口的逻辑上
  • 【机器学习、神经网络、计算机视觉】 trick

    数据处理 flatten a matrix X of shape a b c d to a matrix X flatten of shape b c d a is to use X flatten X reshape X shape 0
  • blender学习笔记

    原型文章 https blog csdn net qq 38906523 article details 78843349 中文翻译版 https blog csdn net qq 38906523 article details 7962
  • css in js开发利器 - styled-components(样式组件)

    styled components 是一个常见的 css in js 类库 和所有同类型的类库一样 通过 js 赋能解决了原生 css 所不具备的能力 比如变量 循环 函数等 注意 有时候 React 版本和 styled componen
  • socket编程之服务器端与客户端(代码实例)

    在我们学习的过程中 对TCP IP UDP Socket编程这些词应该有所了解了 随着网络技术的发展 这些词充斥着我们的耳朵 那么我想介绍一下 什么是TCP IP UDP socket在哪里呢 socket通信是什么呢 socket接口函数
  • 【算法刷题】算法题解题方法技巧及典例汇总

    关键词 算法 二分查找 DFS BFS 动态规划 滑动窗口 位运算 前言 Leetcode刷题目的 无疑是提高自己的编程和算法能力 算法是面试逃不过的环节 之前都是刷每日一题 然后也有大半年没刷了 感觉并未真正学到啥东西 也没记住啥 之后开
  • 从0开始springboot后台管理项目-mybatis-plus/druid链接数据库多数据源

    1 准备完成的功能 通过mybatis plus druid进行数据库链接 配置多数据源 使用mybatis plus的原因就是太强大 比如支持Lambda 依赖少等等优点 可以搜索一下mybatis plus和mybatis的区别 2 m
  • 如何安装pip3以及第三方python库(for Mac)

    环境 OS 10 12 3 16D32 macOS Sierra Python3 Python 3 6 1 什么是pip Python之所以强大 其中一个原因是其丰富的第三方库 pip则是python第三方库的包管理工具 由于在Mac上py
  • Win10多用户同时远程桌面,并各自操作互不干扰

    微软Server版操作系统默认是支持多用户登陆的 例如Windows Server 2012 而Win10操作系统正常情况下是不允许用户同时远程的 即一个用户远程进来会把另一个用户踢掉 因此需要破解才能使得多个用户同时登陆远程桌面 也即需要
  • 笔记22-1(C语言进阶 动态内存管理)

    目录 注 为什么存在动态内存分配 动态内存函数的介绍 malloc和free calloc realloc 常见的动态内存错误 1 对NULL指针的解引用操作 2 对动态开辟空间的越界访问 3 使用free函数释放了非动态开辟的空间 4 使
  • 多线程间的5种通信方式

    问题 有两个线程 A 线程向一个集合里面依次添加元素 abc 字符串 一共添加十次 当添加到第五次的时候 希望 B 线程能够收到 A 线程的通知 然后 B 线程执行相关的业务操作 线程间通信的模型有两种 共享内存和消息传递 以下方式都是基本
  • 西门子S7-200PLC的自锁

    自锁 百度 交流接触器通过自身的常开辅助触头使线圈总是处于得电状态的现象叫做自锁 在通常的电路中 按下开关 电路通电 松开开关 电路又断开了 一旦按下开关 就能够自动保持持续通电 直到按下其它开关使之断路为止 这样的电路 称为自锁电路 置位
  • CocosCreator 游戏小地图/地图雷达

    更多笔记和源码请关注 微信公众号 CocosCreator笔记 演示 ps 请注意左上角 技术摘要 大地图与小地图坐标转换 更新小地图中元素及视口位置 拖动小地图中视口位置 更新Main Camera位置 实现 01 小地图 图片 的宽高比
  • 1、CMM与CMMI的关系 2、软件全面质量管理的思想体系

    1 CMM与CMMI的关系 CMMI即CMM集成 是系统工程和软件工程的集成成熟度模型 CMMI更适合于信息系统集成企业 CMMI是在CMM基础上发展起来的 它继承并发扬了CMM的优良特性 借鉴了其他模型的优点 融入了新的理论和实际研究成果
  • React Dva项目引入antd UI框架

    上文 React 搭建DvaJS开发环境中我们大家了一个Dva的开发环境 那么 下面 我们就用dva项目引入一下antd 我们平时做react开发 主要也都会选择它 我们直接在项目终端执行 npm install antd 4 24 2 b
  • [转]基于TDOA声源定位算法仿真--MATLAB仿真

    转自 http t cn AiTjYCqD 关注微信公众号 通信小课堂 获取专业小知识 声源定位算法是利用麦克风阵列进行声音定位 属于宽带信号 传统的MUSIC和DOA算法并不适用该场景 本仿真主要用TDOA算法进行定位 常用的阵列信号定位
  • 深入MySQL查询过程底层原理,我找到了MySQL查询慢的根本原因!

    V xin ruyuanhadeng获得600 页原创精品文章汇总PDF 前言 接上一节 那么 一次查询的全过程是什么样的呢 这个时候 我们通过各种百度和Google 然后加上自己的理解 终于搞明白了MySQL一次查询的全过程了 首先 用户