前言

如果面试官问的是,为什么Mysql中Innodb的索引结构采取B+树?这个问题时,给自己留一条后路,不要把B树喷的一文不值。因为网上有些答案是说,B树不适合做文件存储系统的索引结构。如果按照那种答法,自己就给自己挖了一个坑,很难收场。因此,就有了这篇文章的诞生~

正文

这里的Mysql指的是Innodb的存储引擎下的索引结构,其他存储引擎我们暂时不讨论。

B树和B+树

开头,我们先回忆一下,B树和B+树的结构以及特点,如下所示:B树

注意一下B树的两个明显特点

  • 树内的每个节点都存储数据
  • 叶子节点之间无指针相邻

B+树

注意一下B+树的两个明显特点

  • 数据只出现在叶子节点
  • 所有叶子节点增加了一个链指针

针对上面的B+树和B树的特点,我们做一个总结(1)B树的树内存储数据,因此查询单条数据的时候,B树的查询效率不固定,最好的情况是O(1)。我们可以认为在做单一数据查询的时候,使用B树平均性能更好。但是,由于B树中各节点之间没有指针相邻,因此B树不适合做一些数据遍历操作。

(2)B+树的数据只出现在叶子节点上,因此在查询单条数据的时候,查询速度非常稳定。因此,在做单一数据的查询上,其平均性能并不如B树。但是,B+树的叶子节点上有指针进行相连,因此在做数据遍历的时候,只需要对叶子节点进行遍历即可,这个特性使得B+树非常适合做范围查询。

因此,我们可以做一个推论:没准是Mysql中数据遍历操作比较多,所以用B+树作为索引结构。而Mongodb是做单一查询比较多,数据遍历操作比较少,所以用B树作为索引结构。

那么为什么Mysql做数据遍历操作多?而Mongodb做数据遍历操作少呢?因为Mysql是关系型数据库,而Mongodb是非关系型数据。

那为什么关系型数据库,做数据遍历操作多?

而非关系型数据库,做数据遍历操作少呢?我们继续往下看

关系型VS非关系型

假设,我们此时有两个逻辑实体:学生(Student)和班级(Class),这两个逻辑实体之间是一对多的关系。毕竟一个班级有多个学生,一个学生只能属于一个班级。关系型数据库我们在关系型数据库中,考虑的是用几张表来表示这二者之间的实体关系。常见的无外乎是,一对一关系,用一张表就行。一对多关系,用两张表。多对多关系,用三张表。那这里,我们需要用两张表表示二者之间逻辑关系,如下所示

那我们,此时要查cname为1班的班级,有多少学生怎么办?
假设cname这列,我们建了索引!
执行SQL,如下所示!

而这,就涉及到了数据遍历操作!

因为但凡做这种关联查询,你躲不开join操作的!既然涉及到了join操作,无外乎从一个表中取一个数据,去另一个表中逐行匹配,如果索引结构是B+树,叶子节点上是有指针的,能够极大的提高这种一行一行的匹配速度!

有的人或许会抬杠说,如果我先执行

获得cid后,再去循环执行

就可以避开join操作呀?

对此,我想说。你确实避开了join操作,但是你数据遍历操作还是没避开。你还是需要在student的这张表的叶子节点上,一遍又一遍的遍历!

那在非关系型数据库中,我们如何查询cname为1班的班级,有多少学生?非关系型数据库有人说,你可以这么设计?也就是弄两个集合如下所示

然后,执行两次查询去获得结果!一次去class集合查,获得id后再去student集合查。

确实,这么设计是可以的,我没说不行。只是不符合非关系型数据库的设计初衷。在MongoDB中,根本不推荐这么设计。虽然,Mongodb中有一个$lookup操作,可以做join查询。但是理想情况下,这个$lookup操作应该不会经常使用,如果你需要经常使用它,那么你就使用了错误的数据存储了(数据库):如果你有相关联的数据,应该使用关系型数据库(SQL)。

因此,正规的设计应该如下

假设name这列,我们建了索引!
我只需执行一次语句

db.class.find( { name: '1班' } )

这样就能查询出自己想要的结果。

而这,就是一种单一数据查询!毕竟你不需要去逐行匹配,不涉及遍历操作,幸运的情况下,有可能一次IO就能够得到你想要的结果。

因此,由于关系型数据库和非关系型数据的设计方式上的不同。导致在关系型数据中,遍历操作比较常见,因此采用B+树作为索引,比较合适。而在非关系型数据库中,单一查询比较常见,因此采用B树作为索引,比较合适。

面试套路

目前套路有如下几种

套路一

你简历写了mysql,没写mongodb!面试官:"说说mysql索引结构?"我:"巴拉巴拉"面试官:"知道为什么用B+树,不用B树么?"这个时候正常的面试者就蒙了,会把B树的缺点喷一通!于是乎下一问就是面试官:"其实一些非关系型数据库,如mongodb用的就是B树,你知道原因么?"

然后你就回去等通知了!

套路二

你简历写了mysql,也写了mongodb!这种情况更完美!面试官:"说说mysql索引结构?"我:"巴拉巴拉"面试官:"你简历写了Mongodb,有了解过他的索引结构么?"我:"巴拉巴拉"面试官:"为什么Mongodb索引用B树,而Mysql用B+树?"然后你就回去等通知了!

套路三

你简历既没写mysql,没写mongodb!面试官;"如果你来设计数据库,你会对他的索引用什么数据结构?"我:"首先不考虑红黑树这类,巴拉巴拉…应该会用B树或者B+树。"面试官;“如果我要设计一个像Mongodb那样的非关系型数据库,我要用什么数据结构当索引比较合适?”然后你就可以回去等通知了!

上面三个套路都是真实存在的!总之,只要面试官想问这个问题,都可以绕到这个问题上去!

面试官:为什么Mysql中Innodb的索引结构采取B+树?的更多相关文章

  1. 《MySQL实战45讲》学习笔记4——MySQL中InnoDB的索引

    索引是在存储引擎层实现的,且在 MySQL 不同存储引擎中的实现也不同,本篇文章介绍的是 MySQL 的 InnoDB 的索引. 下文将以这张表为例开展. # 创建一个主键为 id 的表,表中有字段 ...

  2. 面试官:Mysql 中主库跑太快,从库追不上怎么整?

    写这篇文章是因为之前有一次删库操作,需要进行批量删除数据,当时没有控制好删除速度,导致产生了主从延迟,出现了一点小事故. 今天我们就来看看为什么会产生主从延迟以及主从延迟如何处理等相关问题. 坐好了, ...

  3. MySQL中的联合索引学习教程

    MySQL中的联合索引学习教程 这篇文章主要介绍了MySQL中的联合索引学习教程,其中谈到了联合索引对排序的优化等知识点,需要的朋友可以参考下   联合索引又叫复合索引.对于复合索引:Mysql从左到 ...

  4. MySQL存储引擎MyISAM和InnoDB,索引结构优缺点

    MySQL存储引擎MyISAM和InnoDB底层索引结构 深入理解MySQL索引底层数据结构与算法 (各种索引结构优缺点) Myisam和Innodb索引实现的不同(存储结构) 存储引擎作用于什么对象 ...

  5. MySQL中的聚集索引和辅助索引

    MySQL中的聚集索引和辅助索引 当你定义一个主键时,innodb存储引擎就把他当做聚集索引 如果你没有定义一个主键,则innodb定位到第一个唯一索引,且改索引的所有列值均为非空,就将其当做聚集索引 ...

  6. MySql中innodb存储引擎事务日志详解

    分析下MySql中innodb存储引擎是如何通过日志来实现事务的? Mysql会最大程度的使用缓存机制来提高数据库的访问效率,但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据 ...

  7. MySQL中InnoDB锁不住表的原因

    MySQL中InnoDB锁不住表是因为如下两个参数的设置: mysql> show variables like '%timeout%'; +-------------------------- ...

  8. 高性能MySQL中的三星索引

    高性能MySQL中的三星索引 我对此提出了深深的疑问: 一星:相关的记录指的是什么??(相关这个词很深奥,“相关部门”是什么部门) 二星:如果建立了B-Tree(B+Tree)索引,数据就有序了.三星 ...

  9. mysql 中 innoDB 与 MySAM

    mysql 中 innoDB 与 MyISAM 的特点 --ENGINE = innodb 1.提供事务处理,支持行锁: 2.不加锁读取,增加并发读的用户数量和空间: 3. insert/update ...

随机推荐

  1. SQLyog连接数据库报错 plugin caching_sha2_password could not be loaded

    错误如图所示: 问题描述: 下载新版的 mysql 8.0.11 安装. 为了方便安装查看,我下载了sqlyog 工具 连接 mysql. 配置新连接报错:错误号码 2058 问题分析: mysql ...

  2. [前端、HTTP协议、HTML标签]

    [前端.HTTP协议.HTML标签] 什么是前端 """ 任何与用户直接打交道的操作界面都可以称之为前端 比如:电脑界面 手机界面 平板界面 什么是后端 后端类似于幕后操 ...

  3. [Java]数据分析--数据可视化

    时间序列 需求:将一组字符顺序添加到时间序列中 实现:定义时间序列类TimeSeries,包含静态类Entry表示序列类中的各项,以及add,get,iterator,entry方法 TimeSeri ...

  4. Linux下script命令录制、回放和共享终端操作script -t 2> timing.log -a output.session # 开始录制

    Linux下script命令录制.回放和共享终端操作 [日期:2018-09-04] 来源:cnblogs.com/f-ck-need-u  作者:骏马金龙 [字体:大 中 小]   另一篇终端会话共 ...

  5. openshift 3.11 安装部署

    openshift 3.11 安装部署 openshift安装部署 1 环境准备(所有节点) openshift 版本 v3.11 1.1 机器环境 ip cpu mem hostname OSsys ...

  6. too many open files问题详解

    too many open files问题详解 feelgood3000关注0人评论2616人阅读2018-08-23 09:47:52   一  单个进程打开文件句柄数过多 ulimit中的nofi ...

  7. 046.Python协程

    协程 1 生成器 初始化生成器函数 返回生成器对象,简称生成器 def gen(): for i in range(10): #yield 返回便能够保留状态 yield i mygen = gen( ...

  8. 戴尔 R730xd 服务器更改管理口密码 图文教程

    一.开机根据提示按F2进入配置界面 - 选择中间的iDRAC Setting选项,回车确认 二.进入之后选择 user configuration 选项 三.在change password 处键入新 ...

  9. 5.7 echo:显示一行文本

    echo命令 能将指定的文本显示在Linux命令行上.     -n    不要自动换行 -E    不解析转义字符(默认参数)   -e    若字符串中出现以下字符,则需要进行特别处理,而不会将它 ...

  10. 【数据结构与算法】多种语言(VB、C、C#、JavaScript)系列数据结构算法经典案例教程合集目录

    目录 1. 专栏简介 2. 专栏地址 3. 专栏目录 1. 专栏简介 2. 专栏地址 「 刘一哥与GIS的故事 」之<数据结构与算法> 3. 专栏目录 [经典回放]多种语言系列数据结构算法 ...