一、前言

为了讲清楚这个问题,我们要先了解什么是索引。

我记得刚刚学习数据库的时候,老师喜欢用书本的目录来类比数据库的索引,并告诉我们索引能够像目录一样,让我们更快地找到想要找到的数据。

如果是第一次接触索引,这个比喻能够让我们有一个直观的印象。但是当深入去学习索引的时候,我们不能继续持有索引即目录的思想,我们要跳出来去思考索引的本质是什么。

二、索引的本质

在没有索引的情况下,我们查找数据只能按照从头到尾的顺序逐行查找,每查找一行数据,意味着我们要到到磁盘相应的位置去读取一条数据。

如果把查询一条数据分为到磁盘中查询和比对查询条件两步的话,到磁盘中查询的时间会远远大于比对查询条件的时间,这意味着在一次查询中,磁盘io占用了大部分的时间。更进一步地说,一次查询的效率取绝于磁盘io的次数,如果我们能够在一次查询中尽可能地降低磁盘io的次数,那么我们就能加快查询的速度。

在知道了减少磁盘io能加快查询速度后,我们就要聚焦于如何减少磁盘io。如果按照原表逐行查询的话,n条数据就要查询n次,也就是O(N)的时间复杂度,为了减少磁盘io的次数,我们必须用一种查询时间复杂度更低的数据结构来保存数据。

这种查询时间复杂度低的数据结构,我们称之为索引。所以通俗来说,索引其实就是某种数据结构,能充当索引的数据结构是多种多样的。

三、索引的选择

既然索引是一种便于查询的数据结构,如果大家对数据结构有一定了解的话,大概率会首选树型结构。毕竟树型结构普遍有着O(logN)的查询时间复杂度,而且插入删除数据的性能也比较平均。(可能你会说数组,哈希表的查询速度也很高啊,这个后面也会分析)

虽然我们都已经知道Mysql中最常用的引擎像InnoDB和MyISAM,最终都选择了B+树作为索引,但是这里我还是打算从最常见的二叉树开始讲起,推导一下为什么最终选择了B+树作为索引,并比较一下几种树型结构在充当索引时的优劣。

二叉树

最普通的二叉树的问题在于他不能保证O(logN)的查询时间复杂度,我们看下面的图:

由于插入的元素逐渐增大,元素始终在右边进行插入,好好的一棵二叉树最终变成了一条“链表”。在这种极端的情况下,二叉树的查询时间复杂度不再是O(logN),而是退化为O(N),这样显然不符合索引的要求。

平衡二叉树(红黑树)

像红黑树这样的平衡二叉树,无论如何插入元素,他都可以通过一些旋转的方法调整树的高度,使得整棵树的查询效率维持在O(logN),如下图所示:

这么来说他已经符合了成为索引的必备条件,但是最终没有选择他作为索引说明还有不足的地方。仔细看看可以发现平衡二叉树的每个节点只有两个孩子节点,如果一张表的数据量特别大,整棵树的高度也会随之上升。一个千万级别的表如果用平衡二叉树作为索引的话,树高将会达到二十多层。这也就意味着做一次查询需要二十多次磁盘io,这是一个不小的开销。

那么有没有能在大数据量的情况下,还能保持一个较小树高的树型结构呢?

B树和B+树

答案就是B树。上面我们说到了平衡二叉树的瓶颈在于一个节点只有两个孩子节点,而B树一个节点可以存放N个孩子节点,这就完美解决了树高的问题,我们可以把B树称为平衡多叉树,B树作为索引如下图所示:

但是以B树的结构作为索引仍有可以优化的地方,我们先看看最终的B+树,再仔细分析B+树在B树的基础上作了哪些改进,为什么B+树最终能够胜任索引的工作:

从图片中可以看到B+树同样是一棵多差平衡树,和B树一样很好地解决了树高的问题。

改进点一:

但仔细看可以发现,B树的节点中既存储索引,也存储表对应的数据;而B+树的非叶子节点是不存储数据的,只存储索引,数据全部存储在叶子节点上。

为什么要做这样的改进?我们做一次算术就知道了。

假设树高为2,主键ID为bigint类型,长度为8字节,节点指针为6字节,一行数据记录的大小为1k,一次io操作能获得一页16k的数据。

在索引为B+树的情况下,根节点能存储:16k / (6 + 8) = 1170 条索引指针;到了第一层,一共能指向 1170 * 1170 = 1368900 条索引指针;到了最底一层叶子节点,一个节点能存储16k / 1k = 16 条记录,一共能存储 1170 * 1170 * 16 = 21902400 条记录

在B树的情况下,由于非叶子节点使用了大量空间存储数据,存放的索引指针肯定就少,最终整棵树如果想要存储和B+树一样多的数据就必须要增加树高,这样一来就增加了磁盘io,所以说B+树作为索引的性能比B树高。

改进点二:

叶子节点之间使用指针连接,提高区间访问效率。如果我们要进行范围查询,可以轻松通过B+树叶子节点之间的指针进行遍历,减少了不必要的磁盘io。

总结

看到这里,相信大家对为什么Mysql的常用引擎都默认使用B+树作为索引已经有了初步的认知。我们只要牢记一点:索引是为了减少磁盘io提高查询性能而存在的。

最后回应一下为什么不常用哈希表和数组作为索引

哈希表虽然单一个值的查询效率很高,但是撑不住范围查询,哪个公司的业务还没个范围查询呢?

而数组虽然查询的效率高,但是增加和删除的效率低,由于记录在增加和删除的时候索引也得跟着维护,这会导致大数据量的情况下,增加或删除一条记录效率较低。

为什么Mysql的常用引擎都默认使用B+树作为索引?的更多相关文章

  1. MySQL 的常用引擎

    1. InnoDB InnoDB 的存储文件有两个,后缀名分别是 .frm 和 .idb,其中 .frm 是表的定义文件,而 idb 是数据文件. InnoDB 中存在表锁和行锁,不过行锁是在命中索引 ...

  2. mysql的常用引擎

    在MySQL数据库中,常用的引擎主要就是2个:Innodb和MyIASM. 首先: 1.简单介绍这两种引擎,以及该如何去选择.2.这两种引擎所使用的数据结构是什么. 1. a.Innodb引擎,Inn ...

  3. MySQL数据库常用引擎

    在MySQL数据库中,常用的引擎主要就是2个:Innodb和MyIASM. 首先: 1.简单介绍这两种引擎,以及该如何去选择.2.这两种引擎所使用的数据结构是什么. 1. a.Innodb引擎,Inn ...

  4. 为什么用B+树做索引&MySQL存储引擎简介

    索引的数据结构 为什么不是二叉树,红黑树什么的呢? 首先,一般来说,索引本身也很大,不可能全部存在内存中,因此索引往往以索引文件的方式存在磁盘上.然后一般一个结点一个磁盘块,也就是读一个结点要进行一次 ...

  5. 2020-05-18:MYSQL为什么用B+树做索引结构?平时过程中怎么加的索引?

    福哥答案2020-05-18:此答案来自群员:因为4.0成型那个年代,B树体系大量用于文件存储系统,甚至当年的Longhorn的winFS都是基于b树做索引,开源而且好用的也就这么个体系了.B+树的磁 ...

  6. Mysql 常用引擎的特点及选择使用策略

    Mysql 常用引擎的特点及选择使用策略 Mysql数据库常用存储引擎 Mysql数据库是一款开源的数据库,支持多种存储引擎的选择,比如目前最常用的存储引擎有:MyISAM,InnoDB,Memory ...

  7. mysql中有多种存储引擎,每种引擎都有自己的特色

    mysql中有多种存储引擎,每种引擎都有自己的特色. 用途: MyISAM:快读, Memory:内存数据, InnoDB:完整的事务支持 锁: MyISAM:全表锁定, Memory:全表锁定, I ...

  8. MySql的多存储引擎架构, 默认的引擎InnoDB与 MYISAM的区别(滴滴)

    1.存储引擎是什么? MySQL中的数据用各种不同的技术存储在文件(或者内存)中.这些技术中的每一种技术都使用不同的存储机制.索引技巧.锁定水平并且最终提供广泛的不同的功能和能力.通过选择不同的技术, ...

  9. 简单描述MySQL常用引擎的特点及MySQL的逻辑架构

    目录 表的分类数据库引擎? 首先得说说mysql的逻辑架构,它整体分为3层: 常用引擎: 补充知识点: 表的分类数据库引擎? 引擎是什么? 引擎就是一个系统最核心的部分,比如汽车的发动机,人的心脏 数 ...

随机推荐

  1. MySQL5.7彻底取消主从复制

    由于手误在master节点执行了stop slave;->change master to XXX;->start slave;的动作,后面虽然使用stop slave停止了主从复制,但是 ...

  2. Windows 下 LaTeX 手动安装宏包(package)以及生成帮助文档的整套流程

    本文简单介绍如何手动安装一个 LaTeX 宏包. 一般来说,下载的 TeX 发行版已经自带了很多宏包,可以满足绝大部分需求,但是偶尔我 们也可能碰到需要使用的宏包碰巧没有安装的情况,这时我们就需要自己 ...

  3. 记 MySQL优化 20条

    1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的.当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一 ...

  4. K-means真的不能使用曼哈顿距离吗?

    问题 说到k-means聚类算法,想必大家已经对它很熟悉了,它是基于距离计算的经典无监督算法,但是有一次在我接受面试时,面试官问了我一个问题:“k-means为什么不能使用曼哈顿距离计算,而使用欧式距 ...

  5. 一位资深程序员大牛推荐的Java技术学习路线图

    Web应用,最常见的研发语言是Java和PHP. 后端服务,最常见的研发语言是Java和C/C++. 大数据,最常见的研发语言是Java和Python. 可以说,Java是现阶段中国互联网公司中,覆盖 ...

  6. vmware workstaion之不能连接外网

    Vmwareworkstation15系列桥接模式不能上网解决办法 最近在vmwareworkstation15中创建一个双网卡虚拟机,由于一直连不了外网,一直困扰着我.各种姿势在百度谷歌查找,最终还 ...

  7. 操作系统-CPU管理的直观想法

    1. 管理CPU,先要使用CPU 管理CPU的最直观方法 2. 提出问题 有IO指令执行的特别慢,当cpu执行计算指令很快,遇到IO指令cpu进行等待,利用率不高. 使用多道程序.交替执行,这样cpu ...

  8. koa01

    1.koa简介 koa是express团队开发的一个更加轻量级的服务端开发框架,也是未来的趋势 2.安装 npm i -g koa-generator //全局安装koa脚手架 3.创建项目 koa2 ...

  9. javascript输入用户名,在服务器中显示出了

    ## 第一个文件 pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Tra ...

  10. 手机浏览器自动播放视频video(设置autoplay无效)的解决方案

    1.问题的提出 某一天接了个需求,需要在手机的H5页面内加入视频,我开开心心做完,准备交付的时候,问题来了,PM想要用户一进入页面,视频就开始播放,不需要用户手动点击. 2.尝试解决 加autopla ...