【原创】为什么Mongodb索引用B树,而Mysql用B+树?
引言
好久没写文章了,今天回来重操旧业。毕竟现在对后端开发的要求越来越高,大家要做好各种准备。
因此,大家有可能遇到如下问题
为什么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,如下所示!
SELECT *
FROM t_student t1, (
SELECT cid
FROM t_class
WHERE cname = '1班'
) t2
WHERE t1.cid = t2.cid
而这,就涉及到了数据遍历操作!
因为但凡做这种关联查询,你躲不开join操作的!既然涉及到了join操作,无外乎从一个表中取一个数据,去另一个表中逐行匹配,如果索引结构是B+树,叶子节点上是有指针的,能够极大的提高这种一行一行的匹配速度!
有的人或许会抬杠说,如果我先执行
SELECT cid
FROM t_class
WHERE cname = '1班'
获得cid后,再去循环执行
SELECT *
FROM t_student
WHERE cid = ...
就可以避开join操作呀?
对此,我想说。你确实避开了join操作,但是你数据遍历操作还是没避开。你还是需要在student的这张表的叶子节点上,一遍又一遍的遍历!
那在非关系型数据库中,我们如何查询cname为1班的班级,有多少学生?
非关系型数据库
有人说,你可以这么设计?也就是弄两个集合如下所示

然后勒,执行两次查询去获得结果!
确实,这么设计是可以的,我没说不行。只是不符合非关系型数据库的设计初衷。在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那样的非关系型数据库,我要用什么数据结构当索引比较合适?”
然后你就可以回去等通知了!
上面三个套路都是真实存在的!总之,只要面试官想问这个问题,都可以绕到这个问题上去!
总结
其实这篇文章很早以前就想写,后来一直耽搁着。今天有时间刚好补上,希望大家有所收获。
【原创】为什么Mongodb索引用B树,而Mysql用B+树?的更多相关文章
- 为什么Mongodb索引用B树,而Mysql用B+树?
引言 好久没写文章了,今天回来重操旧业. 今天讲的这个主题,是<面试官:谈谈你对mysql索引的认识>,里头提到的一个坑. 也就是说,如果面试官问的是,为什么Mysql中Innodb的索引 ...
- 为什么 MongoDB (索引)使用B-树而 Mysql 使用 B+树
B-树由来 定义:B-树是一类树,包括B-树.B+树.B*树等,是一棵自平衡的搜索树,它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点.B-树是专门为外部存储器设计的,如磁盘,它对 ...
- mongodb,redis,memcached,mysql对比
1.性能都比较高,性能对我们来说应该都不是瓶颈总体来讲,TPS方面redis和memcache差不多,要大于mongodb 2.操作的便利性memcache数据结构单一redis丰富一些,数据操作方面 ...
- java实现哈弗曼树和哈夫曼树压缩
本篇博文将介绍什么是哈夫曼树,并且如何在java语言中构建一棵哈夫曼树,怎么利用哈夫曼树实现对文件的压缩和解压.首先,先来了解下什么哈夫曼树. 一.哈夫曼树 哈夫曼树属于二叉树,即树的结点最多拥有2个 ...
- Qt实现表格树控件-自绘树节点虚线
目录 一.开心一刻 二.自绘树节点? 三.效果展示 四.实现思路 1.可扩展接口 2.函数重写 3.同步左侧表头 五.相关文章 原文链接:Qt实现表格树控件-自绘树节点虚线 一.开心一刻 一程序员第一 ...
- HYSBZ - 3813 奇数国 欧拉函数+树状数组(线段树)
HYSBZ - 3813奇数国 中文题,巨苟题,巨无敌苟!!首先是关于不相冲数,也就是互质数的处理,欧拉函数是可以求出互质数,但是这里的product非常大,最小都2100000,这是不可能实现的.所 ...
- 为什么 MySQL 使用 B+ 树
为什么 MySQL 使用 B+ 树是面试中经常会出现的问题,很多人对于这个问题可能都有一些自己的理解,但是多数的回答都不够完整和准确,大多数人都只会简单说一下 B+ 树和 B 树的区别,但是都没有真正 ...
- B树的进化版----B+树
C++为什么叫C plus plus?这是由于C++相当于继承C的语法后,增加了各方面的能力,所扩展出的一种新语法.在软件领域中 plus 有增加的味道.在这里B +树也一样,是B树的增强版.在学习B ...
- 深入理解索引和AVL树、B-树、B+树的关系
目录 什么是索引 索引的分类 索引和AVL树.B-树.B+树的关系 AVL树.红黑树 B-树 B+树 SQL和NoSQL索引 什么是索引 索引时数据库的一种数据结构,数据库与索引的关系可以看作书籍和目 ...
随机推荐
- Pandas 数据分析,高中体测练习
分析体测成绩 需求: 体侧成绩转变成分数 开卷考试 excel完成可以 pandas读取excel代码中 完成 一个手输入 进一步,画图,分布,体重正常,肥胖,偏瘦比例,绘制饼图 男生跑步1000成绩 ...
- Salesforce LWC学习(十) 前端处理之 list 处理
本篇参看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array list是我们经 ...
- 2019牛客暑期多校第二场题解FH
F.Partition problem 传送门 题意:有2n个人,分两组,每组n个,要求sum(vij)最大值. 题解:n并不大我们可以枚举每个人是在1组还是2组爆搜. 代码: #include &l ...
- 【转】【e周美文】优秀博客上榜推荐
Everybody,本周的博客推荐开始啦,记住,有好的博客可要给小活推荐一下哦. 7.19日 博客推荐 Android权限列表作者:@大漠落日 链接:http://my.eoe.cn/1103623/ ...
- Java控制台五子棋(纯算法)
Java五子棋小游戏 本方案是基于控制台写的一个代码 没有花里胡哨的界面,只为研究算法 仅仅用了200行代码 下面是的是运行结果 游戏运行结果 这里我就很简单的复制了一个结果 第9回合,下子方:玩家2 ...
- php部署后错误排查流程
未使用框架的php程序不可用时,没有框架提供的调试信息,因此要按照请求的整个生命周期来调试程序, 具体错误依次排查网络,服务器,环境,代码的步骤层层深入,最终定位到错误的发生点. 1 访问程序部署的服 ...
- graphviz 的使用教程
node 节点属性如下 : Name Default Values color black node shape color comment any string (format-dependen ...
- java实现FTP文件下载
package com.vingsoft.util;/*** @author 作者:dujj* @version 创建时间:2020年1月13日 下午5:53:39*/import java.io.F ...
- 阿里云Centos7.X 如何对外开放端口
一句话:如果你是买的各大厂商的云服务器,去安全组配置对应需要使用到的端口就可以啦! 因为博主用的是阿里云,所以这里就只介绍下阿里云如何开放端口,按着下面三张图来操作就行嘞 这个时候有同学就说了,不通过 ...
- pycharm 安装vue
1.设置JS为ES6 2.安装vue.js 3.重启pycharm 4.检查