引言

好久没写文章了,今天回来重操旧业。毕竟现在对后端开发的要求越来越高,大家要做好各种准备。

因此,大家有可能遇到如下问题

为什么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),这两个逻辑实体之间是一对多的关系。毕竟一个班级有多个学生,一个学生只能属于一个班级。

关系型数据库

我们在关系型数据库中,考虑的是用几张表来表示这二者之间的实体关系。常见的无外乎是,一对一关系,用一张表就行。一对多关系,用两张表。多对多关系,用三张表。

那这里,我们需要用两张表表示二者之间逻辑关系,如下所示

那我们,此时要查cname1班的班级,有多少学生怎么办?

假设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的这张表的叶子节点上,一遍又一遍的遍历!

那在非关系型数据库中,我们如何查询cname1班的班级,有多少学生?

非关系型数据库

有人说,你可以这么设计?也就是弄两个集合如下所示

然后勒,执行两次查询去获得结果!

确实,这么设计是可以的,我没说不行。只是不符合非关系型数据库的设计初衷。在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+树?的更多相关文章

  1. 为什么Mongodb索引用B树,而Mysql用B+树?

    引言 好久没写文章了,今天回来重操旧业. 今天讲的这个主题,是<面试官:谈谈你对mysql索引的认识>,里头提到的一个坑. 也就是说,如果面试官问的是,为什么Mysql中Innodb的索引 ...

  2. 为什么 MongoDB (索引)使用B-树而 Mysql 使用 B+树

    B-树由来 定义:B-树是一类树,包括B-树.B+树.B*树等,是一棵自平衡的搜索树,它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点.B-树是专门为外部存储器设计的,如磁盘,它对 ...

  3. mongodb,redis,memcached,mysql对比

    1.性能都比较高,性能对我们来说应该都不是瓶颈总体来讲,TPS方面redis和memcache差不多,要大于mongodb 2.操作的便利性memcache数据结构单一redis丰富一些,数据操作方面 ...

  4. java实现哈弗曼树和哈夫曼树压缩

    本篇博文将介绍什么是哈夫曼树,并且如何在java语言中构建一棵哈夫曼树,怎么利用哈夫曼树实现对文件的压缩和解压.首先,先来了解下什么哈夫曼树. 一.哈夫曼树 哈夫曼树属于二叉树,即树的结点最多拥有2个 ...

  5. Qt实现表格树控件-自绘树节点虚线

    目录 一.开心一刻 二.自绘树节点? 三.效果展示 四.实现思路 1.可扩展接口 2.函数重写 3.同步左侧表头 五.相关文章 原文链接:Qt实现表格树控件-自绘树节点虚线 一.开心一刻 一程序员第一 ...

  6. HYSBZ - 3813 奇数国 欧拉函数+树状数组(线段树)

    HYSBZ - 3813奇数国 中文题,巨苟题,巨无敌苟!!首先是关于不相冲数,也就是互质数的处理,欧拉函数是可以求出互质数,但是这里的product非常大,最小都2100000,这是不可能实现的.所 ...

  7. 为什么 MySQL 使用 B+ 树

    为什么 MySQL 使用 B+ 树是面试中经常会出现的问题,很多人对于这个问题可能都有一些自己的理解,但是多数的回答都不够完整和准确,大多数人都只会简单说一下 B+ 树和 B 树的区别,但是都没有真正 ...

  8. B树的进化版----B+树

    C++为什么叫C plus plus?这是由于C++相当于继承C的语法后,增加了各方面的能力,所扩展出的一种新语法.在软件领域中 plus 有增加的味道.在这里B +树也一样,是B树的增强版.在学习B ...

  9. 深入理解索引和AVL树、B-树、B+树的关系

    目录 什么是索引 索引的分类 索引和AVL树.B-树.B+树的关系 AVL树.红黑树 B-树 B+树 SQL和NoSQL索引 什么是索引 索引时数据库的一种数据结构,数据库与索引的关系可以看作书籍和目 ...

随机推荐

  1. 22.Python安装和卸载第三方模块方法

    安装和卸载第三方开源模块的步骤:下例,安装urllib3模块的步骤. 1.安装开源模块步骤: 按键盘windows键+r键,输出cmd回车.或开始->windows系统->命令提示符: 输 ...

  2. Windows 7 + Tiny Linux 4.19 + XFS + Vmware Workstation 15 (PRO) 下篇dockerの奥义

    美好的事物总是来自不易,而我是一个docker新手 从以上开场,请各位follow me站在一个初学者的角度,一步一步用最简单的视角审视docker和它的真实存在 上篇预告:Windows 7 + T ...

  3. 【记】本地远程连接VM VirtualBox中虚拟机Centos6的数据库MySQL

    目标:远程连接虚拟机中的MySQL 效果图如下 1. VBox设置好端口转发 具体步骤请看 VM VirtualBox 网络地址转换(NAT)使用详解 2. MySQL授权 如果这时我们就去远程连接M ...

  4. Asp.Net Core 学习教程1、初始.Net Core与VS Code 第一个web程序

    1..Net Core介绍 .NET Core是.NET Framework的新一代版本, 是微软开发的第一个具有跨平台(Windows.Macosx.Linux) 能力的应用程序开发框架,未来也将会 ...

  5. Jaeger容器化部署

    概述 Jaeger是由Uber开源的分布式追踪系统,一套完整的Jager追踪系统包括Jaeger-client.Jaeger-agent.Jaeger-collector.Database和Jaege ...

  6. 微信小程序点击图片放大

    WXML: <view class='imgList'> <view class='imgList-li' wx:for='{{imgArr}}'> <image cla ...

  7. Spring Boot2 系列教程 (二) | 第一个 SpringBoot 工程详解

    微信公众号:一个优秀的废人 如有问题或建议,请后台留言,我会尽力解决你的问题. 前言 哎呦喂,按照以往的惯例今天周六我的安排应该是待在家学学猫叫啥的.但是今年这种日子就可能一去不复返了,没法办法啊.前 ...

  8. mysql时间类型和格式转换

    内容目录 简介mysql时间类型DATE_FORMAT()函数 简介 今天开发中,做一个功能需要对历史数据进行补充,相信大家也遇到过这样的情况,这个历史数据需要按月份和人的id进行区分,于是想到了my ...

  9. UVA540 Team Queue——题解 by hyl天梦

    UVA540 Team Queue 题解 题目描述:题目原题 https://vjudge.net/problem/UVA-540 Queues and Priority Queues are dat ...

  10. 2019CSP初赛游记

    Day 0 作为一个初三的小蒟蒻…… 对于J+S两场比赛超级紧张的…… 教练发的神奇的模拟卷…… 我基本不会…… 就这样吧…… Day 1 Morning 不知道怎么就进了考场…… 周围坐的全是同学( ...