MySQL:InnoDB存储引擎的B+树索引算法
很早之前,就从学校的图书馆借了MySQL技术内幕,InnoDB存储引擎这本书,但一直草草阅读,做的笔记也有些凌乱,趁着现在大四了,课程稍微少了一点,整理一下笔记,按照专题写一些,加深一下印象,不枉读了一遍书。与此同时,也加深一下对MySQL的了解,认识了原理,对优化的原则才有把握,对问题的分析才有源头。
关于B+树数据结构
①InnoDB存储引擎支持两种常见的索引。
一种是B+树,一种是哈希。B+树中的B代表的意思不是二叉(binary),而是平衡(balance),因为B+树最早是从平衡二叉树演化来的,但是B+树又不是一个平衡二叉树。
同时,B+树索引并不能找到一个给定键值的具体行。B+树索引只能找到的是被查找数据行所在的页。然后数据库通过把页读入内存,再在内存中进行查找,最后得到查找的数据。
先从二分查找法说起:
二分查找法的基本思想是,将记录排序(假如从小到大排序),然后采用跳跃式的方式进行查找,以有序数列的中点位置为比较对象,如果要找的元素小于该中点元素,那么查找左半部分,如果要找的元素大于该中点元素,那么久找右半部分。比如一组排好序的数:5 10 19 22 30 55 59 60 90, 如果我要查找60这个数字,那么先找30,发现30小于60,那么找30右半部分的中点59,发现59还是小了,那么找59右边的数,从而找到了60,这样通过不断二分把查找需要的时间以指数级进行下降,算法效率到了Logn级别。
再说一下平衡二叉树:


这是一幅平衡二叉树,左子树的值总是小于根的值,右子树的值总是大于根的键值,因此可以通过中序遍历(以递归的方式按照左中右的顺序来访问子树),因此遍历以后得到的输出是9、17、28、35、39、56、65、87。这样,如果要查找键值为28的记录,先找到根,然后发现根大于28,找左子树,发现左子树的根17小于28,再找下一层右子树,然后找到28。通过了3次查找找到了需要找的节点。但是如果二叉树节点分布非常不均匀,就像第二张图那样,那么如果要查找39这个节点的话,查找效率和顺序查找就差不多了,最差的结果就是查找65,那么二叉搜索树就会完全退化成线性表。因此如果想要最大性能地构造一个二叉查找树,需要这颗二叉查找树是平衡的,平衡二叉树对于查找的性能是比较高的,但是不是最高的,只是接近最高的性能。要达到最好的性能,需要建立一颗最优二叉树,但是最优二叉树的建立和维护需要大量的操作,因此用平衡 二叉树就比较好。同时,平衡二叉树多用于内存结构对象中,因此维护他的开销相对较小。
②为什么使用B+树呢?
虽然二叉查找树和平衡二叉树都能够实现较快的数据查找,但是,由于数据库的内容是存在于磁盘上,而磁盘IO与内存IO相比,比内存IO慢了10^5~10^6倍,为了减少磁盘IO,提高检索速度,因而才用了B+树这种数据结构。换言之,B+树就是为磁盘或其他直接存取辅助设备而设计的一种多路查找树,是多叉树。
③什么是B+树,其特性是什么
B+树的概念还是过于复杂,直接上图比较合适,来一张维基百科上的截图:

从上面可以看出,所有记录的节点都在页节点中,并且是顺序存放的,如果我们从最左边的节点开始遍历,可以得到的所有键值的顺序是:1、2、3、4、5、6、7。
在B+树中,所有记录节点都是按照键值的大小顺序存放在同一层的叶节点中,各个叶子节点通过指针进行连接。由于一个节点中存放了多条的数据,那么检索的时候,进行的磁盘IO次数将会少掉很多。
在B+树插入的时候,为了保持平衡,对于新插入的键值可能需要做大量的拆分页操作,而B+树主要用于磁盘,因此页的拆分意味着磁盘操作,因此应该在可能的情况下尽量减少页的拆分。因此,B+树提供了旋转的功能。至于旋转和删除等内容,过于复杂,这篇笔记先不做记录。只是了解使用B+树的原因以及B+树的特性。
关于索引
InnoDB存储引擎使用聚集索引,实际的数据行和相关键值保存在一块。因而,在InnoDB中要使用索引访问数据始终需要两次查找,而不是一次。因为索引叶子节点中存储的不是行的物理位置,而是主键的值。即:二次索引-->主键-->数据的叶子-->通过数据叶字节点中的page directory找到数据行。
因为每一张InnoDB的表都会有一个主键索引,但是如果没有显式指定怎么办?如果没有手工去指定主键索引的话,那么,InnoDB引擎会指派一个unique的列作为主键,如果没有unique的字段的话,那么便会自动生成一个隐含的列作为主键。
所以,在在InnoDB的设计中,应该尽可能的使用一个与业务无关auto_increment的自增主键,而不要去使用uuid之类的随机(无序)的聚集键。同时,由于所有的索引都使用主键的索引,如果主键索引过长,也会使辅助索引相应的变大。
聚集索引的存储并不是物理上的连续,而是逻辑上连续的。一方面,页通过双向链表连接,页按照主键的顺序排列;另一方面,每个页中的记录也是通过双向链表进行维护,物理存储上可以同样不按照主键存储。
对于目前的MySQL来说,所有的对于索引的添加或者删除操作,MySQL数据库都是要先创建一张新的临时表,然后再把数据导入临时表,再删除原来的表,然后再把临时表命名为原来的表。所以,如果一张表中数据太多的话,那么后期添加删除索引需要花费很长的时间,因而最好在数据库设计初期便设计好索引。
还有,虽然InnoDB存储引擎从版本innoDB Plugin开始,支持一种称为快速索引创建的方法,但是这种方法只限定于辅助索引,对于主键的创建和删除还是需要重建一张表。
更好的资料:
[2]《MySQL技术内幕:InnoDB存储引擎》
MySQL:InnoDB存储引擎的B+树索引算法的更多相关文章
- InnoDB存储引擎的B+树索引算法
关于B+树数据结构 ①InnoDB存储引擎支持两种常见的索引. 一种是B+树,一种是哈希. B+树中的B代表的意思不是二叉(binary),而是平衡(balance),因为B+树最早是从平衡二叉树演化 ...
- InnoDB存储引擎的 B+ 树索引
B+ 树是为磁盘设计的 m 叉平衡查找树,在B+树中,所有的记录都是按照键值的大小,顺序存放在同一层的叶子节点上,各叶子节点组成双链表.叶节点是数据,非叶节点是索引. 首先,需要清楚:B+ 树索引并不 ...
- MySQL InnoDB存储引擎体系架构 —— 索引高级
转载地址:https://mp.weixin.qq.com/s/HNnzAgUtBoDhhJpsA0fjKQ 世界上只两件东西能震撼人们的心灵:一件是我们心中崇高的道德标准:另一件是我们头顶上灿烂的星 ...
- 浅析Mysql InnoDB存储引擎事务原理
浅析Mysql InnoDB存储引擎事务原理 大神:http://blog.csdn.net/tangkund3218/article/details/47904021
- MySQL技术内幕InnoDB存储引擎(五)——索引及其相关算法
索引概述 索引太多可能会降低运行性能,太少就会影响查询性能. 最开始就要在需要的地方添加索引. 常见的索引: B+树索引 全文索引 哈希索引 B+树索引 B+树 所有的叶子节点存放完整的数据,非叶子节 ...
- MySQL InnoDB 存储引擎探秘
在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库中.从MySQL5.5.8开始,InnoDB成为其默认的存储引擎.InnoDB存储引擎支持事务.其设计目标主要是面向OLTP的应用, ...
- MySQL InnoDB 存储引擎原理浅析
注:本文主要基于MySQL 5.6以后版本编写,多数知识来着书籍<MySQL技术内幕++InnoDB存储引擎>,本文章仅记录个人认为比较重要的部分,有兴趣的可以花点时间读原书. 一.MyS ...
- MySQL InnoDB存储引擎
200 ? "200px" : this.width)!important;} --> 介绍 本篇文章是对Innodb存储引擎的概念进行一个整体的概括,innodb存储引擎的 ...
- mysql innodb存储引擎介绍
innodb存储引擎1.存储:数据目录.有配置参数为“ innodb_data_home_dir ” .“ innodb_data_file_path ” 和 “innodb_log_group_ho ...
随机推荐
- matlab squeeze函数的用法
matlab中squeeze函数用于删除矩阵中的单一维(Remove singleton dimensions),比如执行下面的代码,随机产生一个1x2x3的矩阵A,然后squeeze(A)将返回一个 ...
- 用java操作XML文件(DOM解析方式)
XML 可扩展标记语言(Extensible Markup Language),是独立于软件和硬件的传输工具. XML的作用: (1)用作配置文件 (2)简化数据共享 (3)简化数据传输 XML DO ...
- [刘阳Java]_Java技术有哪些学习重点_第1讲
纵观网上有很多非常好的对Java技术的总结,这里我个人谈谈对Java技术学习有哪些重点内容[浮浅之见] Java环境搭建 Java基础语法 Java面向对象编程 Java异常 Java IO流 Jav ...
- apache.http.client.HttpClient
前言 HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源.虽然在 JDK 的 java net包中已经提 ...
- django 创建项目
django-admin startproject project-name 启动服务器 python manage.py runserver 0.0.0.0:8000 配置ALLOW_HOST
- 【温故Delphi】之编译与链接(转)
本文基本转自“Delphi编译/链接过程” @瓢虫Monster,向瓢虫君学习,:) 下图展示了Delphi是怎样编译源文件,并把它们链接起来,最终形成可执行文件的. 当Delphi编译项目(Proj ...
- Android中轴旋转特效实现,制作别样的图片浏览器
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10766017 Android API Demos中有很多非常Nice的例子,这些例 ...
- 将html页改成jsp的两种方式
将html页改成jsp的两种方式 作者: 字体:[增加 减小] 类型:转载 时间:2013-08-13 将html页改成jsp有两种方法,第一种是直接修改html文件,另一种是新建jsp文件.下面为大 ...
- Spring的定时任务配置(转)
spring的定时任务配置分为三个步骤: 1.定义任务 2.任务执行策略配置 3.启动任务 1.定义任务 <!--要定时执行的方法--> <bean id="testTas ...
- pro生成sln
跳转到对应的工程目录,通过执行如下的命令:qmake -tp vc 命令实现