为什么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操作,可以做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中b树索引_Mongo和Mysql中的B树索引相关推荐

  1. mysql中b树是什么_MySQL优化中B树索引知识点总结

    为什么要进行SQL优化呢?很显然,当我们去写sql语句时: 1会发现性能低 2.执行时间太长, 3.或等待时间太长 4.sql语句欠佳,以及我们索引失效 5.服务器参数设置不合理 SQL语句执行过程分 ...

  2. mysql5.6 函数索引_聊聊MySQL中的索引

    关于MySQL中的索引使用 索引是数据库优化中最常用也是最重要的手段之一,通过索引通常可以帮助用户解决大多数的SQL性能问题. 索引的存储分类: 1.B-Tree索引:最常见的索引类型,大部分引擎都支 ...

  3. Mysql 索引 总结 —— 概述 || 索引优势劣势|| 索引结构(索引是在MySQL的存储引擎层中实现的)|| BTREE 结构||B+TREE 结构||MySQL中的B+Tree||索引分类

    索引概述 MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序). 在数据之外,数据库系统还维护者满足特定查找算法的数据结构, 这些数据结构以某种方式引用(指向 ...

  4. mysql为什么采用b树_为什么MongoDB采用B树索引,而Mysql用B+树做索引

    展开全部 事实上,在MySQL数据库中,诸多存储引擎使用的是B+树,即便其名字看上去是BTREE. 4.1 innodb的索引机制 先以innodb存储引擎为例,说明62616964757a68696 ...

  5. hive能加快MySQL查询速度吗_建立索引可以加快表中数据查询的速度吗

    首先明白为什么索引会增加速度,DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合. 如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特 ...

  6. mysql为什么使用b 树作为索引_为什么Mysql用B+树作为索引

    该篇文章已经投稿给公众号hollis 1.什么是索引 索引这个词,相信大多数人已经相当熟悉了.不过为了文章的完整性,这里再啰嗦一下.索引是一种数据结构,用于帮助我们在大量数据中快速定位到我们想要查找的 ...

  7. mysql 跳表 b 树_简单谈谈Mysql索引与redis跳表

    摘要 面试时,交流有关mysql索引问题时,发现有些人能够涛涛不绝的说出B+树和B树,平衡二叉树的区别,却说不出B+树和hash索引的区别.这种一看就知道是死记硬背,没有理解索引的本质.本文旨在剖析这 ...

  8. B树、B-树、B+树、B*树【转】,mysql索引

    B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B ...

  9. mysql not null 索引_MySQL中 IS NULL、IS NOT NULL、!= 能用上索引吗?

    看面试题的时候,总能看到MySQL在什么情况下用不上索引,如下: MySQL的WHERE子句中包含 IS NULL.IS NOT NULL.!= 这些条件时便不能使用索引查询,只能使用全表扫描. 不耽 ...

最新文章

  1. Robot Perception for Indoor Navigation《室内导航中的机器人感知》
  2. #if DEBUG vs. Conditional(“DEBUG”)
  3. string.Format格式化输出
  4. 带有emplace开头的STL为何优于其它插入函数
  5. 织梦dede:channelartlist调用排除指定typeid栏目
  6. idea项目乱码问题
  7. POJ 3415 后缀数组+单调栈
  8. 每天一个linux命令(28):diff 命令
  9. Linux进程状态(ps stat)之R、S、D、T、Z、X 转:http://blog.csdn.net/huzia/article/details/18946491...
  10. OpenCV 文字绘制——cv::putText详解
  11. error LNK2001: 无法解析的外部符号unresolved external symbol __imp__JNI_CreateJavaVM@12
  12. 清北2017夏令营考试 day2
  13. 最是人间四月天,细雨点洒樱花前
  14. 什么叫弹性计算云服务器,弹性云服务器
  15. 【第42期】游戏策划:如何让游戏帮助孩子成长?
  16. 增量式编码器与螺旋微动机构的数显电路
  17. 微信小程序列表首字母排序并根据字母定位
  18. 计算机图形学--动画与模拟
  19. 在html5中flex布局详解,Flex布局详解(一)
  20. OpenCV实现简单的录屏功能

热门文章

  1. TCPview 介绍
  2. linux主机操作性日志恢复测试,Linux主机操作系统加固规范标准[详].doc
  3. 【2020蓝桥杯】Python组真题解析 - 第十一届蓝桥杯
  4. jdk ServiceLoader怎么用
  5. goroutine sync.RWMutex读写锁RLock的使用
  6. spark分区增减、JavaFX基本操作和HDFS NN DN概念
  7. 详解spark任务提交至yarn的集群和客户端模式
  8. Docker创建Dockerfile脚本构建jdk1.8镜像并启动容器示例
  9. Linux centos 6.7防火墙打开MySQL 3306端口
  10. BlockingQueue阻塞队列