文章目录

  • 理解索引的特性
  • 索引的本质
  • 其他结构的问题
  • B-Tree 和 B+Tree
  • MySQL索引实现
    • MyISAM索引实现
    • InnoDB索引实现

理解索引的特性

  • 索引是帮助MySQL高效获取数据的排好序的数据结构
  • 索引存储在文件里

MySQL支持多种索引类型,如BTree索引哈希索引全文索引等等。

本文主要讨论BTree索引,这也是我们平时用得最多的索引。


索引的本质

MySQL官方对于索引的定义为:索引是帮助MySQL高效获取数据的数据结构。 即可以理解为:索引是数据结构

我们知道,数据库查询是数据库最主要的功能之一,我们都希望查询数据的速度尽可能的快,因此数据库系统的设计者会从查询算法的角度进行优化。最基本的查询算法当然是顺序查找,当然这种时间复杂度为O(n)的算法在数据量很大时显然是糟糕的,于是有了二分查找、二叉树查找等。

但是二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树,但是数据本身的组织结构不可能完全满足各种数据结构。所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引

接下来看一个示例:

上图展示了一种可能的索引方式。左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址(注意逻辑上相邻的记录在磁盘上也并不是一定物理相邻的)。为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在O(logn2)O(log2n)的复杂度内获取到相应数据。

虽然这是一个货真价实的索引,但是实际的数据库系统几乎没有使用二叉查找树或其进化品种红黑树(red-black tree)实现的,原因会在下文介绍。

本文将只关注于BTree索引,因为这是平常使用MySQL时主要使用到的索引。


其他结构的问题

由于索引无法装入内存,则必然依赖磁盘(或SSD)存储。而内存的读写速度是磁盘的成千上万倍(与具体实现有关),因此,核心问题是“如何减少磁盘读写次数”。
首先不考虑页表机制,假设每次读、写都直接穿透到磁盘,那么:

  • 线性结构:读/写平均O(n)次
  • 二叉搜索树(BST):读/写平均O(log2(n))次;如果树不平衡,则最差读/写O(n)次
  • 自平衡二叉搜索树(AVL):在BST的基础上加入了自平衡算法,读/写最大O(log2(n))次
  • 红黑树(RBT):另一种自平衡的查找树,读/写最大O(log2(n))次

BST、AVL、RBT很好的将读写次数从O(n)优化到O(log2(n));其中,AVL和RBT都比BST多了自平衡的功能,将读写次数降到最大O(log2(n))。

假设使用自增主键,则主键本身是有序的,树结构的读写次数能够优化到树高树高越低读写次数越少;自平衡保证了树结构的稳定。如果想进一步优化,可以引入B树和B+树。

在介绍B树之前,先来看另一棵神奇的树——二叉排序树(Binary Sort Tree),首先它是一棵树,“二叉”这个描述已经很明显了,就是树上的一根树枝开两个叉,于是递归下来就是二叉树了(下图所示),而这棵树上的节点是已经排好序的,具体的排序规则如下:

  • 若左子树不空,则左子树上所有节点的值均小于它的根节点的值
  • 若右子树不空,则右字数上所有节点的值均大于它的根节点的值
  • 它的左、右子树也分别为二叉排序树(递归定义)

从图中可以看出,二叉排序树组织数据时,用于查找是比较方便的,因为每次经过一次节点时,最多可以减少一半的可能,不过极端情况会出现所有节点都位于同一侧,直观上看就是一条直线,那么这种查询的效率就比较低了,因此需要对二叉树左右子树的高度进行平衡化处理,于是就有了平衡二叉树(Balenced Binary Tree)

所谓“平衡”,说的是这棵树的各个分支的高度是均匀的,它的左子树和右子树的高度之差绝对值小于1,这样就不会出现一条支路特别长的情况。于是,在这样的平衡树中进行查找时,总共比较节点的次数不超过树的高度,这就确保了查询的效率(时间复杂度为O(logn))。

参考:https://blog.csdn.net/chuixue24/article/details/86594069


B-Tree 和 B+Tree

目前大部分数据库系统及文件系统都采用 B-Tree 和 B+Tree 作为索引结构。

MySQL InnoDB存储引擎是基于B-树(但实际上MySQL采用的是B+树结构)的索引结构。

注意B-Tree 中文称为 B树没有所谓的B减树,特别是与B+树一起讲的时候。想当然的认为有B+(加)树就有B-(减)树,实际上B+树的英文名是“B+ -Tree”。

B-树是一种m阶平衡树,叶子节点都在同一层,由于每一个节点存储的数据量比较大,索引整个B-树的层数是非常低的,基本上不超过三层。

由于磁盘的读取也是按block块操作的(内存是按page页面操作的),因此B-树的节点大小一般设置为和磁盘块大小一致,这样一个B-树节点,就可以通过一次磁盘I/O把一个磁盘块的数据全部存储下来,所以当使用B-树存储索引的时候,磁盘I/O的操作次数是最少的(MySQL的读写效率,主要集中在磁盘I/O上)。

那么MySQL最终为什么要采用B+树存储索引结构呢,那么看看B-树和B+树在存储结构上有什么不同?

  • B-树的每一个节点,存了关键字和对应的数据地址,而B+树的非叶子节点只存关键字,不存数据地址。因此B+树的每一个非叶子节点存储的关键字是远远多于B-树的,B+树的叶子节点存放关键字和数据,因此,从树的高度上来说,B+树的高度要小于B-树,使用的磁盘I/O次数少,因此查询会更快一些
  • B-树由于每个节点都存储关键字和数据,因此离根节点进的数据,查询的就快,离根节点远的数据,查询的就慢;B+树所有的数据都存在叶子节点上,因此在B+树上搜索关键字,找到对应数据的时间是比较平均的,没有快慢之分
  • 在B-树上如果做区间查找,遍历的节点是非常多的;B+树所有叶子节点被连接成了有序链表结构,因此做整表遍历和区间查找是非常容易的

B-树的结构图如下:

B+树的结构图如下:


MySQL索引实现

在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,接下来我们主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式。


MyISAM索引实现

MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM索引的原理图:

这里设表一共有三列,假设我们以Col1为主键,则图8是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:

同样也是一颗B+Tree,data域保存数据记录的地址。因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录

MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分。


InnoDB索引实现

虽然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同。

第一个重大区别是InnoDB的数据文件本身就是索引文件。从上文知道,MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

上图是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。

第二个与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域。例如,下图为定义在Col3上的一个辅助索引:

这里以英文字符的ASCII码作为比较准则。聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录

了解不同存储引擎的索引实现方式对于正确使用和优化索引都非常有帮助,例如知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择

下篇博文我们将具体讨论这些与索引有关的使用和优化策略。

MySQL 索引底层实现原理(B-tree、B+tree)相关推荐

  1. MySQL索引底层实现原理 MyISAM非聚簇索引 vs. InnoDB聚簇索引

    MySQL索引底层实现原理 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干,就可以得到索引的本质:索引是数据结构. 我们知道,数据库查询是数据库的 ...

  2. 面试官:MySQL索引底层数据结构原理与性能调优,你能回答多少?

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新,可以微信搜索[小奇JAVA面试]第一时间阅 ...

  3. MySQL索引底层数据结构原理剖析

    一. 前言 1. 说明 我们平时所说的:聚集索引(主键索引),次要索引,覆盖索引,复合索引,前缀索引,唯一索引在MySQL5.7和 8.0版本默认都是使用B+Tree索引,除此之外还有 Hash索引. ...

  4. MySQL索引底层实现原理

    索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干,就可以得到索引的本质:索引是数据结构. 我们知道,数据库查询是数据库的最主要功能之一. ...

  5. 3层b+树索引访问磁盘次数_深入理解MySQL索引底层实现原理丨技术干货

    一.索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干,就可以得到索引的本质:索引是数据结构. 我们知道,数据库查询是数据库的最主要功能之 ...

  6. mysql索引底层实现原理_mysql的索引底层之实现原理

    MySQL索引背后的数据结构及算法原理 一.定义 索引定义:索引(Index)是帮助MySQL高效获取数据的数据结构. 本质:索引是数据结构. 二.B-Tree m阶B-Tree满足以下条件: 1.每 ...

  7. MySQL索引底层实现原理(B树和B+树)

    文章目录 一.B-树索引 1. 理论部分 2. B树 黄色的data表示key索引所在的这一行的数据,data存储的是数据本身内容,还是数据在磁盘上的地址? 关于操作系统从磁盘读取索引文件到内存中的几 ...

  8. MYSQL索引底层原理

    MYSQL索引底层原理 1. 索引的本质 索引是帮助MYSQL高效获取数据的排好序的数据结构. 索引一般以文件形式存储在磁盘上. 2. 按索引的分类 2.1. 按字段约束分类 2.1.1. 普通索引 ...

  9. 深入理解 MySQL 索引底层原理

    hi ,大家好,今天分享MySQL硬核知识,希望大家可以学习到真正的知识,慢慢积累,厚积薄发: 看完本文可以学到什么  一步一步推导出 Mysql 索引的底层数据结构  怎么分析回答技术选型问题 一步 ...

  10. Mysql 索引底层原理

    一步一步推导出 Mysql 索引的底层数据结构. Mysql 作为互联网中非常热门的数据库,其底层的存储引擎和数据检索引擎的设计非常重要,尤其是 Mysql 数据的存储形式以及索引的设计,决定了 My ...

最新文章

  1. C#操作OFFICE一(EXCEL)
  2. redis服务器索引文件删除,Redis基本命令整理
  3. Android 网络通信框架Volley简介(Google IO 2013)
  4. 【C/C++多线程编程之八】pthread条件变量
  5. 时序分析:DTW算法(基于模板)
  6. c语言的一些字符串库函数的自己实现
  7. js 取小数整数部分
  8. 驱动12.移植dm9000驱动程序
  9. cudnn7.6.5下载 solitairetheme8_233小游戏下载安装赚钱-233小游戏下载安装最新版v2.29.4.5...
  10. 下列统计量服从什么分布_第六章 数理统计基本概念
  11. 如何为开源项目做市场
  12. 【板绘必读】完全0基础如何学板绘?
  13. Java自动生成word文档,用心看这篇就够了【重点】
  14. 思科模拟器路由器配置
  15. Java架构师面试十大连环炮
  16. win10 此电脑 网络位置 怎么删除
  17. Manjaro找不到默认键盘布局
  18. 《The Selfish Giant》
  19. error: option --single-version-externally-managed not recognized
  20. Python 3 集合方法 copy( )

热门文章

  1. easyui-combobox实现placeholder提示效果
  2. DisplayObjectContainer 属性和方法
  3. KVM虚拟化相关知识简介(脑补)
  4. pxe无人值守智能安装linux
  5. 联想第三季:PC+时代的航母启航?
  6. 14.软件架构设计:大型网站技术架构与业务架构融合之道 --- 业务架构思维
  7. 7.TCP/IP 详解卷1 --- Ping 程序
  8. 6. Zend Studio
  9. 5. http://kb.cnblogs.com/page/90838/
  10. matlab中删除照片_照片也有隐私,教你如何批量删除数码照片中的相机、光圈和地理位置等 EXIF 信息...