MySQL存储和查询过程

当我们执行一条sql时会经过如下流程,可以看到数据最终是以文件的形式存在

当我们在数据库中建立一张student表时,在文件系统中会创建出如下几个文件

这些数据最终会持久化到文件中,那么这些数据在文件中是如何组织的?难道是一行一行追加到文件中的?其实并不是,数据其实是存到页中的,一页的大小为16k,一个表由很多页组成,这些页组成了B+树

一个表的存储方式如下所示

一行一行的数据组成页,页再组成区,区再组成段,便于管理

页:页是innodb磁盘管理的基本单位,innodb每个页的大小为16k

区:由64个连续的页组成,每个页的大小为16kb,即每个区大约为1MB

段:常见的段有数据段(B+树页节点),索引段(B+树非页节点),回滚段等

我们先从微观的角度看一下页是如何存储数据的?

一个页的格式如下所示

名称 说明
文件头 表示页的信息
页头 表示页的状态信息
最小和最大记录 两个虚拟的记录,表示页中的最小记录和最大记录
用户记录 存储行记录内容
空闲空间 页中还没有被使用的空间
页目录 对用户记录进行索引
文件尾 校验页是否完整

数据会源源不断的插入User Records,当插满时,Free Space也就不复存在了。

页面里面的记录是按照主键值从小到大排序的,构成一个单链表

有的小伙伴可能就会问了,我建的表没有主键,那表的数据该如何组织呢?

  1. 首先判断表中是否有非空唯一索引,如果有则该列即为主键
  2. 如果没有,则添加一个名为row_id的隐藏列作为主键


页面之间通过双链表连接到一起

当我们在一个页中查找数据的时候,难道需要一个一个的遍历链表?

当然不需要,为了提高查找的速率,mysql会把数据进行分组,并用页目录记录每个分组最大记录的地址

每个分组有多少条数据呢?

  1. 第一个分组中的记录只能有1条记录
  2. 最后一个分组中记录条数范围只能在1-8之间
  3. 剩下的分组中记录条数范围只能在1-8之间

如下图所示

蓝色的部分为主键及其对应的数据

当查找记录的时候,先通过页目录找到对应的分组,然后再遍历分组内的链表

举个例子我想查找主键为10的用户记录,5个槽的编号为0,1,2,3,4,查找的过程如下

  1. 先二分得出槽中间的位是(0 + 4) / 2 = 2,2号槽里面的最大记录为8,我们需要从2号槽后面继续搜索记录
  2. 3号槽和4号槽中间的位是(3 + 4) / 2 = 3,3号槽里面的最大记录为12,12 > 10,所以要查找的记录在3号槽
  3. 但是用户记录间的链表是单向的,所以我们可以先到槽2中的8记录,然后沿着链表开始遍历,直到找到目标记录

虽然在一个页中查找数据由于数据目录的存在很快了,但是在一个表中查找数据会不会还是很慢呢?毕竟要沿着链表遍历所有的数据页

MySQL当然不允许这种事情发生,既然我们能给记录建立目录加快查找速度,我们就能给页建立目录加快查找速度,目录的格式为每个页中的最小主键id及其对应的页号(就是页面的地址)

目录也是存在数据页中的,大小为16kb。所以有可能有多个目录,当目录过多时,我们还可以给目录建立目录。如下图所示

这不就是一颗树吗?叶子结点存储记录,非叶子结点存储主键及对应的页地址。这颗树其实就是一颗B+树

以上图为例,我们在表中查询主键为5的数据,查询过程如下

先到根目录中去查,接着到页30去查,再定位到页16,最终查找到记录

接着我们再从宏观角度分析一下数据的存储,这样便于我们分析问题

当使用MyISAM存储数据时,数据和索引是分开的,B+树上储存的是对应记录的地址

当使用InnoDB存储数据时,数据和索引是在一起的,即聚集索引。当然你可以对某个字段建立非聚集索引

聚集索引的叶子结点存储的是用户数据,而非聚集索引叶子结点存储的是被索引的列值及其对应的主键值

当使用主键查询记录时,只需要遍历聚集索引即可。而当使用非聚集索引查询数据时,先遍历非聚集索引找到记录的主键值,再根据主键值到聚集索引上遍历获取数据,即回表

最后为了加深大家的理解,放一个我在面试中遇到的一个挺有意思的问题

假设一颗B+树的主键为bigint,一行数据的大小为1kb,树高为3层,那么它能存储多少数据?

mysql默认一个节点的长度为16KB,一个整数字段索引的长度为8B,另外每个索引还跟着6B的指向其子树的指针。树高为3层,那么前2层用来存索引项,最后1层用来存数据,能存储的数据为

( 16 K B / ( 8 B + 6 B ) ) 2 ∗ ( 16 K B / 1 K B ) = 117 0 2 ∗ 16 = 21902400 (16KB / (8B + 6B)) ^2 * (16KB / 1 KB) = 1170^2 * 16 = 21902400 (16KB/(8B+6B))2∗(16KB/1KB)=11702∗16=21902400

1GB=1024MB
1MB=1024KB
1KB=1024B(字节)
1B=8bit(位)

参考博客

[1]http://liuqh.icu/2019/04/03/db/innodb-storage/
[2]https://bbs.huaweicloud.com/blogs/317532

MySQL实战:数据是如何进行存储和查询的?相关推荐

  1. mysql删除数据不会减少存储占用_Mysql单文件存储删除数据文件容量不会减少的bug与解决方法...

    MySQL的Bug之一:InnoDB ibdata1 never shrinks after data is removed 问题描述 当innodb引擎使用单个文件进行存储的时候,当对数据库中数据进 ...

  2. mysql 存储矩阵数据_mysql-在数据库中存储距离矩阵

    我需要在网页上显示城市附近所有位置的距离矩阵. 我想从Web服务中获取所有这些数据并预先保存在数据库中. 我试图找出最佳的关系数据库设计来保存此类数据. 我要避免冗余数据,也要避免提供最佳性能的设计. ...

  3. mysql实战数据.sql_Mysql实战(DML增删改+Select)

    DML(增删改) insert update delete 说明:update和delete都要写清楚where truncate(清空表) 区别: select(查是最重要的) 简单查询: 去重: ...

  4. mysql 重复数据 distinct_MySQL中distinct语句去查询重复记录及相关的性能讨论

    在 MySQL 查询中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值. 关键词 DISTINCT 用于返回唯一不同的值,就是去重啦.用法也很简单: SELE ...

  5. mysql 查看数据库函数_MySQL数据库中常用查询函数简介

    MYSQL中的常用函数 count(*)--- 相当于统计表的行数,在统计结果的时候,不会忽略列值为NULL的记录. select count(*) from yinxiong; Count(列名) ...

  6. 基于云上分布式NoSQL的海量气象数据存储和查询方案

    前言 气象数据是一类典型的大数据,具有数据量大.时效性高.数据种类丰富等特点.气象数据中大量的数据是时空数据,记录了时间和空间范围内各个点的各个物理量的观测量或者模拟量,每天产生的数据量常在几十TB到 ...

  7. 实战干货|自研数据存储迁移MySQL实战

    背景   最近公司内部在做某自研数据存储的下线工作,这里我们暂且化名其为DistributeSQL,由于DistributeSQL不再进行服务支持,需要迁移项目中使用到该存储到其他数据存储中.   本 ...

  8. MySQL实战45讲——MySQL是怎么保证数据不丢的?

    文章摘抄自林晓斌老师<MySQL实战45讲>.今天这篇文章, 我会继续和你介绍在业务高峰期临时提升性能的方法. 从文章标题"MySQL是怎么保证数据不丢的? ", 你就 ...

  9. Mysql+innodb数据存储逻辑

    Mysql+innodb数据存储逻辑. 表空间由段,区,页组成 ibdata1:共享表空间.即所有的数据都存放在这个表空间内.如果用户启用了innodb_file_per_table,则每张表内的数据 ...

最新文章

  1. 如何防止我的模型过拟合?这篇文章给出了6大必备方法
  2. LoadRunner测试问题及解决方法总结
  3. 思科超融合:主推HyperFlex,押注HCI
  4. java中的成员变量和局部变量的区别_java中成员变量与局部变量区别分析
  5. java怎么设置命令行参数_java 命令行参数
  6. python中条件、循环等
  7. 微软正在开发基于 Rust 的安全编程语言
  8. Transact-SQL 示例 - 触发器的基础及应用
  9. 只有10万元预算买畅销SUV自动车型您选谁?
  10. 计算机基础(01)基础知识
  11. ourplay插件_ourplay64位辅助包
  12. 消防应急疏散指示系统如何在工业厂房项目上应用
  13. html天时分秒倒计时,倒计时(天 时 分 秒)(原创)
  14. android 编程词典,基于Android的英文词典的实现方法
  15. vue如何实现打印功能
  16. 轮询查找连接电脑设备IP地址
  17. VS报出的C2134,C4430,C2238错误
  18. ipv6地址概述——带你了解ipv6与ipv4的不同
  19. Oracle使用json后乱码,nodejs读取本地中文json文件出现乱码解决方法
  20. 一周技术思考(第21期)-人们说脏话的频率是衡量代码质量的唯一标准

热门文章

  1. oracle中sql语句(+)符号的意思
  2. 聊一聊直播利器,连麦直播背后的混流方案
  3. c语言编黑白棋游戏,怎样编制黑白棋(2)
  4. php composer 无法下载,php – Composer“下载失败”错误
  5. 感恩工作平台心得体会_感恩与职场 心得体会
  6. 设计模式的5个常见问题及解决办法
  7. 【原创佳作】用Python自制了一张网页,一键自动生成探索性数据分析报告
  8. 一汽大众t一roc_一汽大众T-ROC正式亮相,百公里油耗仅5.7升,售价14万起!
  9. AI英雄 | 对话Gregory:机器智能和人类智力的不同 就像飞机和鸟的区别
  10. 华为WATCH Buds耳机连接不稳定出现听歌卡顿或断音应该怎么办?