看技术文章是不是很累呢, 这次来个轻松点的~来谈一谈MySQL最主流的数据库引擎 InnoDB 吧~

老王走进一号会议室, 随手打开了灯, 小张紧随其后

"王哥, 找我来干啥啊"

老王挥挥手示意小张坐下, "Boss交给了我们一个艰巨的任务, 不过你不用担心, 最难的部分Boss已经做完了"

小张听完松了口气, "那我们负责干啥?"

"设计一个MySQL的数据库引擎"

"那Boss干了啥"

"Boss把名字起好了, 叫 InnoDB"

"还有呢?" 小张一脸懵逼的看着老王

"没了啊, 做项目最难的不就是起名字嘛" 老王随即说到 "好了, 我们开始定下方案吧, 既然数据库的主要功能是增删改查, 那我们就按顺序一个一个来, 先从增开始吧"

"为了之后讨论方便我们先弄个表吧" 老王起身拿起马克笔在白板上写了一个表结构

Table Name : Userid : primaryKeyname : indexage

存储文件结构

老王 : "我们先从最底层的文件系统开始设计, 如果我要执行一条插入语句, 你觉得应该怎么持久化? 换句话说就是文件系统应该设计成什么样子"

小张 : "嗯 ... 弄个文件一行存一条?"

老王 : "你当做毕业设计呢? 咋不弄个txt都塞进去呢"

小张 : "不是, 王哥你听我说, 可以按照主键排序啊, 这样查找的时候可以二分查找, 插入数据的话先二分查找找到对应的位置, 然后插进去就可以了"

老王 : "这个设计是有问题的, 小时候用铅笔在田字格本上写过作文吧? 在你写完一篇作文之后, 你发现一个字写错了, 可以擦掉这个字然后改成正确的, 但是如果想在中间插一句话, 由于没有地方给你写, 是不是只能把后面的全部擦掉, 重新写一遍? 硬盘就跟田字格本是一样的, 根本不支持在随机位置插入数据, 只能覆盖已经有的数据. 还有一点, 田字格本是一行一行的, 但是硬盘根本没有行这一说, 你可以理解成一页只有一行的田字格, 随机读写只支持按照字节查找, 所谓换行只不过是发现数据里有个换行符才知道你这是要换行了, 本质上换行符对于磁盘来说和其他的数据没有什么区别, 也不知道换行符在哪儿, 所以如果你想知道一条数据是第几行数据只能把前面的数据都扫描一遍, 这个性能就很差了"

小张 : "啊? 那我就有点懵了, 看来只能按照顺序插入了? 那如果主键是UUID, 插入顺序肯定不是有序的, 这怎么办啊? 王哥我没思路了"

老王 : "嗯, 有点难为你了, 你看啊, 虽然硬盘只支持按照字节查找, 但是我们可以人为的分个页, 还是田字格本的例子, 一个本子, 每一页的格子数目都是固定的吧, 比如说一页有300个格子, 那我想读第10页, 是不是只要从第2700个格子开始读300个格子就正好把第10页给读完了?"

小张 : "是这样的, 也就是说一页有固定的大小, 读的时候只要知道页数, 就可以得到页的起始偏移量对吧, 然后呢?"

老王 : "对, 我刚才说的读, 是指读到内存里, 既然读到内存里了, 那么这一页具体有几行, 每一行的 id 是什么是不是就都知道了? 那么现在只需要知道每个 id 所在的页数, 那么这个问题是不是就解决了?"

小张 : "感觉还是没懂, 这个只能在顺序的情况下有用啊, 如果主键是UUID的话, 怎么保持数据的顺序呢"

老王 : "为什么一定要按照顺序保存呢? 我们可以引入索引, 就像你看书都有目录一样. 给你简单的画个图, 就别UUID了, 太长了, 假设我们插入数据的顺序按照 id 排列是 1 3 5 2 4 6 吧, 然后假设一页能存下两行数据, 那么等这几条数据都被插入之后, 磁盘里的数据是这样的"

老王 : "你看看, 这样的话, 数据是按照插入的顺序存储的, 但是即便物理上不延续, 只要在索引上是连续的, 那么是不是无论是指定id查找还是范围查找都很方便了?"

小张 : "是的, 王哥你真厉害, 这样插入数据即便是乱序也不需要擦掉文件重新写了, 只要维护好索引那个页就好了, 那我们就照这个方案走吧"

老王 : "先别急, 你看看这个方案有什么缺点?"

小张 : "嗯 ... 要是非说缺点的话就是, 这里假设的是一页2行数据, 如果实际上一页放了100行数据, 那么要是按照主键 id 进行范围查找的话, 由于每次读都需要读一整页, 那么是不是会浪费很多IO在用不到的数据上呢?"

老王 : "嗯, 总结的非常好, 这个设计是会有这个问题, 这种设计属于堆表的一种, 也就是存储顺序按照插入顺序排放, 和索引完全解耦, 优点就是写入很快, 缺点就是如果按照主键范围查询的话基本都是随机读操作, 而且由于有索引到实际数据页的一个映射过程, 所以往往会多一次硬盘读取"

小张 : "嗯 ... 听你这么说, 应该还有其他更好的设计方案?

老王 : "是的, 这次的设计准备用组织索引表的设计, 不过更好倒是谈不上, 两种设计各有千秋"

小张 : "那那个什么组织索引表堆表的区别是什么呢?"

老王 : "区别就是组织索引表的数据页上数据存储是有序的"

小张 : "王哥你真的不是在逗我嘛, 最开始用田字格本的例子和我说有序的存储会需要擦掉后面的数据的不就是你嘛!"

老王 : "注意我说的是页上的数据是有序的, 但是页本身可以是乱序的"

小张 : "我这更糊涂了, 王哥你给举个例子吧"

老王 : "那就还是刚才那个乱序插入 1 3 5 2 4 6 的例子吧, 给你画个图"

老王 : "我们来看第一个图, 这是插入完1 3 5 三条数据的时候的结构"

小张 : "嗯, 看起来和之前那个没什么区别, 不过这个为什么索引页只有两条呢"

老王 : "由于数据页的内容都是有序的, 所以只需要标出来每一页第一行数据的索引值就可以了, 比如如果要找 id 为 3 的数据, 先看索引页, 发现 3 < 5 所以就去查看页1就可以了, 如果页1里没有这条数据, 就说明这条数据不存在"

小张 : "嗯, 懂了"

老王 : "现在看第二张图, 这是插入完 id 为 2 的数据的结构, 由于 id 为 2 的数据小于5所以需要插在页1中, 但是页1已经满了, 所以只能将页1从中间分开成两个页, 所以 id 为 1 的数据被留在了原来的页, 2 和 3 被划分到了一个新的页里, 虽然 3 被从页1移动到了页3, 但是后续的数据,比如页2并没有受到影响, 所以说数据移动的开销在可控制的范围内"

小张 : "哦, 那第三个图就是 id 为 4 的数据被插入, 由于页3满了所以新开了一个页4, 然后 id=6 的数据由于页2没有满就直接被放在了页2上?"

老王 : "完全正确"

小张 : "那还有个问题我一至没问, 这个索引本身也是个页, 如果索引页满了怎么办呢?"

老王 : "小伙子, 你知道B+树嘛?"

小张 : "哦, 我明白了, 这个图就是一层的B+树!"

老王 : "行, 还算有点脑子, 索引页满了也需要分裂, 本质上和数据页没什么区别, 所以索引页也不一定是连续的, 实际情况中索引页和数据页往往混在一起, 全靠页指针进行查找, 还有数据页之间应该是有指向下一个页和上一个页的指针的, 不过这里我没画出来, 看看B+树你就明白了"

小张 : "那还有个问题, 就是这个方案好多页都没塞满, 那这些空间不就浪费了吗?"

老王 : "对, 就是浪费了, 这个没有什么好的解决办法, 而且乱序插入会频繁的触发页的分裂, 不光更耗费空间, 性能也会差一些, 所以你知道为什么DBA推荐使用递增主键了吧?"

小张 : "对了, 我看最开始那个User表, name 是个辅助索引吧, 辅助索引怎么设计啊, 也是B+树嘛"

老王 : "嗯, 也是B+树, 但是叶子节点咱就别指向数据页了, 直接指向主键, 也是就 id 吧"

小张 : "那查询的时候不就需要先查辅助索引找到主键, 然后需要按照主键再查一遍了吗"

老王 : "你别光想着查询啊, 你别忘了我们这个设计是以主键id为维度的组织索引表, 看看我刚才画的图, 插入 id 为 2 的数据的时候是不是发生了页的分裂, 从而导致 id 为 3 的数据被移动到了页3? 我这里举的例子一页只有两条数据还好, 按照正常情况一页可能几百甚至几千条数据, 我去, 那页一旦分裂, 还要把所有移动的数据的辅助索引指向的数据页都改一遍, 那你可能最坏情况下插一条数据几十秒, 这谁受得了啊"

小张 : "哦哦, 有道理, 文件结构我弄懂了, 接下来呢?"

老王 : "接下来还没想好呢, 今儿先到这儿吧, 回头我再想想, 走, 吃饭去!"

先查询再插入的存储过程怎么写_谈一谈 InnoDB(1) - 底层存储文件结构相关推荐

  1. java 先查询再插入

    在测试代码时发现一个问题: 要实现一个数据库表中user_id和手机号两个字段觉得数据的唯一性,所以我要先进行查询,如果数据存在,则不插入,数据不存在则插入数据.可是当前台打开多个页面时,同时触发这个 ...

  2. 未明确定义列存储过程没问题_使用Apache Kudu和Impala实现存储分层

    当为应用程序的数据选择一个存储系统时,我们通常会选择一个最适合我们业务场景的存储系统.对于快速更新和实时分析工作较多的场景,我们可能希望使用 Apache Kudu ,但是对于低成本的大规模可伸缩性场 ...

  3. jdbc mysql 存储过程查询数据_JDBC连接(MySql)数据库步骤,以及查询、插入、删除、更新等十一个处理数据库信息的功能。...

    主要内容: JDBC连接数据库步骤. 一个简单详细的查询数据的例子. 封装连接数据库,释放数据库连接方法. 实现查询,插入,删除,更新等十一个处理数据库信息的功能.(包括事务处理,批量更新等) 把十一 ...

  4. JDBC连接(MySql)数据库步骤,以及查询、插入、删除、更新等十一个处理数据库信息的功能。...

    主要内容:  JDBC连接数据库步骤. 一个简单详细的查询数据的例子. 封装连接数据库,释放数据库连接方法. 实现查询,插入,删除,更新等十一个处理数据库信息的功能.(包括事务处理,批量更新等) 把十 ...

  5. MySQL数据库将查询结果插入到其它表中

    假如目前只有一个goods表,想要增加一个商品分类信息,简单通过goods表无法完成商品分类的添加,这时可以再创建一个商品分类表,把goods表中的商品分类信息添加到该表中,将goods表中的分类名称 ...

  6. 将查询结果插入到现有表中

    在数据库日常维护工作中,我们可能经常需要把某个查询结果插入到现有的表中.如需要把两张表进行合并.需要把另外一张报纸能够符合条件的的记录插入到现有的表中.需要把另外一张表中的某些字段重新整理后插入到现有 ...

  7. mysql查询语句能否让一个字段不显示出来_天天写order by,你知道Mysql底层如何执行吗?

    作者:不才陈某 前言 在实际的开发中一定会碰到根据某个字段进行排序后来显示结果的需求,但是你真的理解order by在 Mysql 底层是如何执行的吗?假设你要查询城市是苏州的所有人名字,并且按照姓名 ...

  8. 【SQL数据库】数据库的创建、查询、插入等操作使用方法(结合黑皮书教材网站(db-book中的例子)在MySQL Workbench和shell中实现查询操作

    SQL 数据库的创建.查询.插入等操作使用方法(结合黑皮书教材网站中的例子) 注:数据来源: https://www.db-book.com/university-lab-dir/sample_tab ...

  9. oracle数据库触发器怎么查询后插入,[求助][Oracle][ORA-00604][ORA-02067]触发器被触发时向远程数据库插入数据...

    环境: 数据库:Oracle 12c:数据库A(本地),数据库B(远程),在A中创建DBLink连接到B 工具:sqldevloper 问题: 数据库A中的Change表中创建了触发器T,After ...

最新文章

  1. Hbase数据模型 列族
  2. Problem 77:Prime summations
  3. javascript中涉及到汉字的比较
  4. 怎样能用计算机打出表白数字,怎么用数字表白?盘点数字表白暗语
  5. springboot web 服务器选择
  6. VC中操作INI文件的API
  7. Kinect开发笔记之六Kinect Studio的应用
  8. 面试 技术 教训_我如何应用从失败的技术面试中学到的经验教训来获得5个工作机会
  9. createprocess重启程序_win32取CreateProcess启动程序的返回值
  10. 2014年3月新鲜出炉的最佳 JavaScript 工具库
  11. 如何优雅地将Markdon格式文件md转为pdf?(使用typora)
  12. 计算机与计算机视觉史话
  13. 全双工音频播放器在c#中使用waveIn / waveOut api
  14. UnityWebPlayer的日志文件在哪
  15. AutoCAD dwg(dxf)图外有多余的点或者线解决办法
  16. linux wget 磁力链接,Linux安装Aria2来实现种子、磁力下载
  17. Docker简介/安装/使用
  18. 好好说话之Chunk Extend/Overlapping
  19. python if多个条件并列_Python中if有多个条件处理方法
  20. 【嵌入式】关于IAP+Xmodem从外部接收bin文件对芯片进行升级学习记录

热门文章

  1. mysql里面的sql_mysql工作中的sql
  2. linux 源码 调试,开发一个Linux调试器(六):源码级逐步执行
  3. linux高通平台代码,高通linux系统初始化
  4. mysql目录权限设置_MySQL文件及目录权限设置分析-爱可生
  5. Python 中关于 round 函数的小坑
  6. python中read()、readline()、readlines()函数
  7. 没看完这11 条,别说你精通 Python 装饰器
  8. php 多维数组按值排序,按子值对php多维数组排序
  9. c语言内存拷贝 memcpy()函数
  10. 如何在C++中调用python程序?