MySQL 索引底层数据结构实现
文章目录
- 概述
- 讨论范围
- 查询数据结构
- 查询数据结构种类及其高性能查询原理
- MySQL 索引的底层数据结构
- MySQL 索引的需求分析
- 选择 MySQL 索引的底层数据结构
- B- 树和 B+ 树的对比
- MySQL 索引的底层数据结构揭秘
概述
MySQL
的索引是存储引擎用于快速找到记录的一种数据结构,是提升 SQL
执行效率的神器。
在正确建立及使用索引的情况下,查询性能将会有非常大的提升(从 O(N)
提升到 O(logN)
,几乎接近于常数级别);但在索引建立不正确或者使用不正确的情况下,将会进行全表扫描(O(N)
),查询性能就比较低下了。
讨论范围
为了不给读者带来可能的理解上的偏差以及困扰,在这里首先说明,本文中讨论的索引是 MySQL
中 InnoDB
存储引擎所使用的索引。
查询数据结构
为了方便大家理解 MySQL
索引的底层数据结构,以及索引为什么能够提升查询性能,首先从查询数据结构开始讲解。
查询数据结构,光从字面上可能不太好理解。但是基于实际含义的角度上来看,或许应该叫便于查询的数据结构,又或者叫高性能的查询数据结构比较贴切。
即,查询数据结构是一种能提升数据查询效率的数据结构。
查询数据结构种类及其高性能查询原理
常见的查询数据结构,有以下几种:
- 有序数组:一个数组,数组中的元素已经全部有序。利用其有序的性质,使用二分查找可以获得
O(logN)
时间复杂度的查询效率 - 跳表:一个链表(单或双向都可以),链表中的所有节点都有序,且在原有链表的基础上增加了一级或多级索引。利用其有序+索引性质,使用二分查找可以获得
O(logN)
时间复杂度的查询效率 - 哈希表:一种维护了键和值的唯一映射关系的数据结构,其本质是将键通过哈希函数+解决哈希冲突的某种手段散列到数组中的一种方法。利用数组的随机访问能力,可以获得在最好情况下
O(1)
查询时间复杂度,最坏情况的时间复杂度取决于哈希函数与解决哈希冲突的方法有关。 - 二叉搜索树:一种节点间有序的二叉树(具体定义在这里就不展开讲了)。利用其有序的性质,使用二分查找在最好情况下可以获得
O(logN)
时间复杂度的查询效率,最坏情况下为O(N)
- 红黑树:一种自平衡的二叉搜索树。利用其有序的性质,使用二分查找可以获得
O(logN)
时间复杂度的查询效率 B-
树:B-
树,是一种自平衡的多叉搜索树。利用其有序的性质,使用二分查找可以获得O(logN)
时间复杂度的查询效率B+
树:B+
树,也是一种自平衡的多叉搜索树。利用其有序的性质,使用二分查找可以获得O(logN)
时间复杂度的查询效率
可以看出,上面的数据结构,除了哈希表外,其余的数据结构都是利用了有序
这个性质,并结合二分查找方法,即可获得较高的(O(N)
时间复杂度)查询效率。
唯一一个例外是二叉搜索树在最坏情况下(在节点分布极其不均匀,几乎退化成单向链表的情况下),会退化成线性搜索,其复杂度为 O(N)
,如下图所示:
可以看到,这个二叉搜索树,几乎已经退化成了一条单向链表,所以其查询时间复杂度将会是 O(N)
。
所以我们得出一个结论:想要提高查询效率,最好利用一个数据有序,且能自平衡(或者不需要平衡操作)的数据结构,再结合二分查找方法,即可达到目标。
在上面这个,最重要的一点就是数据必须有序
,因为如果数据无序,那么二分查找也无用武之地。
MySQL 索引的底层数据结构
假设你是 MySQL
的 InnoDB
存储引擎的开发人员,你会选择哪种数据结构作为索引底层的数据结构呢?
MySQL 索引的需求分析
想要实现一个功能,首先得分析清楚这个功能的需求是什么。现在我们想要实现 MySQL
的索引,那么索引的功能需求是什么呢?
总的来说 MySQL
的索引有以下几个需求点:
- 能够大幅度提升查询性能
- 能支持范围查询
- 易于维护,维护的时间复杂度应该尽可能地低
- 从磁盘读入内存的每个数据页应该包含尽可能多的信息
- 能尽可能地减少磁盘
IO
次数
选择 MySQL 索引的底层数据结构
弄清楚需求后,我们使用排除法来筛选所有可用的查询数据结构:
- 有序数组:不能满足
3、4、5
,排除。有序数组随机插入和删除元素的复杂度为O(N)
,且有序数组在数据量较大时,将数据从磁盘读入内存的IO
次数将不可控 - 跳表:不能满足
4、5
,排除。跳表与有序数组相同,从磁盘读入内存的每个数据页取决于数据本身的大小;在数据量较大时,将数据从磁盘读入内存的IO
次数将不可控 - 哈希表:不能满足
2
,排除。哈希表不支持范围查询 - 二叉搜索树:不能自平衡,排除
- 红黑树:不能满足
4、5
,排除。红黑树虽然能自平衡,但是在数据量较大的情况下,树的高度将会非常大,将数据从磁盘读入内存的IO
次数也会非常多 B-
树:基本可以满足所有条件B+
树:可以满足所有条件
经过上面的比对,我们最终确定了 B-
树和 B+
树两种数据结构可以满足我们的需求,那么这两种数据结构哪种更适合用于实现 MySQL
的索引呢?
B- 树和 B+ 树的对比
B-
树和 B+
树,两者都属于自平衡的多叉搜索树。但是从细节上来说,两者之间有如下的区别:
B+
树只有在叶子节点上才会携带数据,而B-
树在每个节点上都会携带数据- 这个特性决定了
B+
树在非叶子节点上存储的关键字数量越多,那么树的阶就会越大,则树中的节点就会越少,则树的高度就会越低 - 树的高度越高,则每次查询的时候需要进行的磁盘
IO
操作就会越多 - 树的阶越大,即非叶子节点上存储的关键字数量越多,则从磁盘读入内存的每个数据页所包含的信息数量就越多
- 这个特性决定了
B+
树对于范围查询的性能更高B+
树的所有叶子节点组成了一个有序的链表,在进行范围查询时,只需要遍历叶子节点组成的链表就行B-
树在进行范围查找时,需要反复地中序遍历,才能获得范围内的所有数据
下面的图说明了在存储同一组数据时,B-
树和 B+
树的区别:
在这里,我们模拟 B-
树因为所有节点都要存储数据,所以阶为 3
的情况;而 B+
树只有在叶子节点上才会存储数据,所以阶会比 B-
树要大,这里设定为 4
。
可以看到,在存储同一组数据时,B-
树的高度比 B+
树要高;且 B+
树的所有叶子节点组成了一个有序链表,范围查询时更方便也更高效。
MySQL 索引的底层数据结构揭秘
根据上面的分析,我们可以得出,要实现 MySQL
索引,底层数据结构选择 B+
树最为合适。而实际上,MySQL
的 InnoDB
存储引擎也确实是使用 B+
树作为底层的数据结构的。
而 InnoDB
除了实现标准的 B+
树功能外,还有以下的实现细节值得关注:
InnoDB
数据页的大小(由参数innodb_page_size
决定)决定了B+
树的节点的大小,也决定了这个节点上存储的关键字数量- 默认的一个页的大小为
16KB
,高度为3
的B+
树即可存储千万级别的数据量
- 默认的一个页的大小为
- 叶子节点组成的链表为双向链表,可以更方便也是更高效地处理范围查询
MySQL 索引底层数据结构实现相关推荐
- 面试官:MySQL索引底层数据结构原理与性能调优,你能回答多少?
哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新,可以微信搜索[小奇JAVA面试]第一时间阅 ...
- Mysql——索引底层数据结构与Explain用法
Mysql--索引底层数据结构与Explain用法 一.索引底层数据结构 1.Mysql不同引擎对应的数据结构 2.B+Tree数据结构 2.1. 二叉树 (Binary Search Trees) ...
- MySQL索引底层数据结构
MySQL相信大家都不陌生,索引的日常使用应该也是比较频繁的,今天就聊一聊索引底层的数据结构; MySQL索引底层为什么使用B+树而不是二叉树;红黑树;B树? 索引:索引是帮助MySQL高效获取数据的 ...
- mysql索引数据结构图解_深入理解Mysql索引底层数据结构与算法
索引的定义:索引(Index)是帮助MySQL高效获取数据的数据结构. Q1:大家使用索引有没有想过这个问题?为什么索引能够帮助mysql高效获取数据?我一一给大家道来!在给大家讲之前,先更大家分享一 ...
- mysql 联合主键_深入理解Mysql索引底层数据结构与算法,背后的故事
引言 索引是帮助MySQL高效获取数据的排好序的数据结构 索引数据结构对比 二叉树 左边子节点的数据小于父节点数据,右边子节点的数据大于父节点数据.如果col2是索引,查找索引为89的行元素,那么只需 ...
- mysql 索引底层数据结构与算法
索引:是帮助MySQL高效获取数据的排好序的数据结构. mysql 索引的底层数据结构: 二叉树:如果是规律性数据,比如1,2,3.....等数据,存储容易成线性结构,数据规模太大之后,查询太慢. 红 ...
- MySQL索引底层数据结构原理剖析
一. 前言 1. 说明 我们平时所说的:聚集索引(主键索引),次要索引,覆盖索引,复合索引,前缀索引,唯一索引在MySQL5.7和 8.0版本默认都是使用B+Tree索引,除此之外还有 Hash索引. ...
- MySQL索引底层数据结构详解
索引是帮助MySQL高效获取数据的排好序的数据结构 索引的数据结构: 1.二叉树 通过一个简单的插入你可以看到,二叉树的插入会根据每个节点进行判断,每一个节点右边的数据一定是大于等于这个节点数据,而他 ...
- 腾讯三面灵魂问题:如何理解MySQL索引底层数据结构
MySQL 索引相关的数据结构有两种,一种是 B+tree,一种是 Hash,那么为什么在 99.99% 很多情况下都使用的是 B+tree索引呢? 索引的底层数据结构是怎样的呢? 接下来就听小二娓娓 ...
最新文章
- linux如何连接移动硬盘
- 预测分析:R语言实现2.6 特征选择
- c ++向量库_在C ++中对2D向量进行排序
- 互联网日报 | 5月25日 星期二 | 华为再次重申不造车;贝壳宣布左晖为公司“永远的荣誉董事长”;清华大学成立量子信息班...
- 恶心的Oracle的if else if...
- 新浪微博澄清“花钱撤热搜”、“花钱压热搜”等不实传言
- vscode为各自项目添加launch和setting
- 微信小程序开发:学习笔记[5]——JavaScript脚本
- Android腾讯微博开放平台入门(四)发表一条文字微博
- Ubuntu学习笔记(2)---安装LumaQQ
- 双十一会场体验 SSR 优化 - 走向更复杂的渲染架构
- 人类迁徙计划 (feat.译者补完篇)
- 《HelloGitHub》第 67 期
- 膨胀卷积dilated convolution 相关
- 用python绘制玫瑰花
- vue 封装饿了么文件上传组件实现图片上传
- Elasticsearch:创建属于自己的 Ingest processor
- docker教程(简介)
- 星速配资:能耗双控双刃剑 造纸板块一飞冲天
- 2017 Material design 第三章第一节《颜色》
热门文章
- 计算机等级考试真题演示,全国计算机等级考试二级真题测试(答案)四、演示文稿题-日...
- c语言哈夫曼压缩文本,哈夫曼文本压缩C语言实现.doc
- Java String indexOf(int ch)方法与示例
- 面试官:你说说互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景?
- 实战:Redis 集群模式(下)
- vb的一些搞怪的操作
- PyQt5 QTreeWidget更改item项前的展开折叠三角图标
- docker-conpose 入门
- List「Object[]」转Map「Integer,String」处理
- C++函数的用法:erase函数