MySQL数据库是我们最常用的关系型数据库之一
也是初学者最喜欢选择数据库
易知,MySQL底层索引是用B 树实现的
传送门:图解:什么是B-树、B 树、B*树
下面就具体说说MySQL索引底层数据结构与算法实现
1.索引是什么
索引(Index)是帮助MySQL高效获取数据的数据结构,相当于数据的目录
2. MySQL的两种搜索引擎
分别是MyISAM搜索引擎和InnoDB搜索引擎
我们经常用到的是InnoDB搜索引擎
2.1 MyISAM搜索引擎
MyISAM引擎使用B Tree作为索引结构
叶节点的data域存放的是数据记录的地址
以Col1为主键,则上图是一个MyISAM表的主索引(Primary key)示意
可以看出MyISAM的索引文件仅仅保存数据记录的地址
在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别
只是主索引要求key是唯一的
而辅助索引的key可以重复
如果我们在Col2上建立一个辅助索引,则此索引的结构
跟主键索引的结构没什么区别
2.2 InnoDB搜索引擎
虽然InnoDB也使用B Tree作为索引结构,但具体实现方式却与MyISAM截然不同
InnoDB引擎索引也叫聚集索引
他的关键字和数据在叶节点上,在一起存储
下图是主键索引的示意图
数据表每一行的数据内容,都是挂接到叶子节点的
InnoDB搜索引擎辅助索引与MyISAM索引的不同是
InnoDB的辅助索引data域存储相应记录主键的值而不是地址
如下图是将名称字段设置为辅助索引的示意图
挂接到叶子节点是主键索引的值
举个栗子
如果我们要查询名称叫Alice的数据
会先通过辅助索引查询到,这条数据的主键是18
然后再通过主键索引进行搜索
找到主键是18的叶子节点
并将数据返回
所以,对于InnoDB搜索引擎,主键索引是非常关键和重要的
3.思考
3.1 为什么一般需要一个自增的数字主键?
在之前的一篇文章中介绍了图解:什么是B-树、B 树、B*树
为了避免出现二叉搜索树那种又高又偏瘫的结构
B 树是具有自平衡能力的
所以在插入数据的时候,有可能会导致整棵树的多个部分发生旋转、合并和拆分操作
同时频繁的移动、分页操作造成了大量的碎片
自增的数字主键,会自动建立索引
在插入数据时,由于主键本身就是自增有序的
可以尽量减少B 树为自平衡而做的旋转、合并和拆分操作
从而提高效率,也可以减少碎片的产生
字符串类型的主键,如果没有什么规律
会导致插入的时候比较随机
可能会导致较多的旋转、合并和拆分操作
如果你没有建立任何主键
那么MySQL中InnoDB引擎是要求表必须有一个主键的
没有手动建立主键,MySQL会将选一个不包含null的字段将它当做主键,并建立索引
如果连这样的字段都没有,就会使用行号生成一个聚集索引,把它当做主键,这个行号大小为6bytes
就是这么强硬
所以最好还是建议新建一个自增的int类型的主键
3.2 为什么MySQL不使用B-树而选择B 实现索引?
这个主要有三个原因
(1)
作为关系型数据库,会有很多区间查询的操作
比如需要查询年龄在18-20岁的小姑娘
而B 树的所有节点会在叶子节点中,并组成了一个增序的链表
这对于区间查询来说是非常高效的
而B-树却不是这样
(2)
我们需要先清楚一个知识点
计算机cpu处理的所有数据,都必须是从内存当中读取(别抬杠,又或者说缓存、寄存器)
计算机需要按照分页或分段的方式将数据从磁盘读取到内容
这个读取过程相对于运算速度,是很慢的
每次读取的数据量也是有限的
所以I/O磁盘操作是影响计算机性能的一个瓶颈
在B-树中,每个节点都有卫星数据
每一个卫星数据Data就是数据表中的一行数据
在从磁盘读取数据表中的数据进行查询时
因为每个节点都带有卫星数据
导致每次I/O读取的节点数目非常有限
而B 树的所有节点都会出现在叶子节点
每一行数据也挂接在叶子节点
非叶子节点仅仅充作索引目录的作用
所以每次I/O操作可以读取更多的节点数量
当找到目标数据的时候,再通过节点中的数据地址信息去读取数据
可以在总体上减少I/O操作,体检查询效率
(3)
依据刚才卫星数据原因
B-在找到节点的时候,其实就是已经拿到了需要的数据
而B 树在找到节点之后,还需要再次I/O操作去读取数据
B-最快的时候1次I/O操作就能拿到数据
而B 树每次都需要遍历到叶子节点才能拿到数据
相对来说,B 树结构的检索性能更具有稳定性
3. 为什么mongodb使用B-树实现索引?
首先B-树相比B 树最大的优势是数据查询的最快时间复杂度是O(1)
文档型模式设计一般会将你所需要的数据都相对集中在一起(内存或硬盘)
数据集中在一起则减少了关系性数据库需要从各个地方去把数据找过来(然后Join)所耗费的随机读时间
而MongoDB的设计要求你常用的数据(working set)可以在内存里装下
内存读写时间相对于磁盘I/0,几乎可以忽略不计
所以,使用B-树的存储结构更适合mongodb文档型数据库的设计理念
下篇博客说一下基于B 树结构的索引,MySQL可以做哪些优化
文/戴先生@2020年6月26日
---end---