索引的作用
索引的作用是快速检索,而快速检索的实现本质是数据结构。通过不同数据结构的选择,实现各种数据的快速检索。
Mysql索引底层数据结构选型
1. hash表
哈希表是做数据快速检索的有效利器。
哈希算法:也叫散列算法,就是把任意值(key)通过哈希函数变换为固定长度的 key 地址,通过这个地址进行具体数据的数据结构。
从时间复杂度来讲,哈希算法是O(1),检索速度非常快,那为什么Mysql没有采取哈希作为其底层算法呢
因为考虑到索引的一个常用手范围查找
如果用哈希做范围查找,一个简单的思路就是一次把数据找出来加载到内存,然后在内存筛选目标范围内的数据,显然这次不行的
2. 二叉查找树
二叉查找树是一种支持快速查找的数据结构,如图所示
二叉查找树的时间复杂度为C(lgn),从检索上看能做到高效检索
那能不能解决哈希算法不能提供的范围查找呢?
答案是肯定的,因为每个节点大于左子树,小于右子树
但是,在极端条件下,二叉查找树会退化成链表,二分查找也会变成遍历查找,时间复杂度退化为O(n),
因此,简单的二叉查找数存在不平衡导致的索引性能下降问题
3.AVL树和红黑树
二叉查找树存在不平衡的问题,因此学者提供了通过树结点的自动旋转调整,让二叉树始终保持平衡的状态,就能保持二叉查找树的最佳性能,基于这种思想的自调节平衡状态的树有AVL树和红黑树
首先简单介绍一种红黑树,这是一颗自动调整树状态的树结构,比如当红黑树出现不平衡的时候,红黑树便会通过自动左旋结点,右旋结点和改变结点颜色调整树状态,使树保持基本平衡,保证查询效率不会明显下降
但是红黑树也存在问题,
如果数据是顺序插入,树的形态会处于‘右倾’的形态,虽然没有二叉查找树那么夸张,但数据库的基本主键一般通过自增操作,这种问题对于查找而言也是极大的消耗
现在考虑另一种更为严格的自平衡二叉树AVL树,AVl树是绝对平衡的的树结构,因此在调整树结构上会消耗更多性能
总结一下AVL树的优点
- 不错的查找性能O(lgn),不存在极端情况下的低效查找
- 可以实现数据的范围查找,数据排序
AVL树结构确实不错,但并不合适做Mysql索引的数据结构,因为考虑一个问题
数据库查询数据的瓶颈在于磁盘I/O,如果使用AVL树,每一个结点只能存放一个数据,每一次磁盘I/O操作只能取一个节点的数据,也就是一个数据,这样查找一个数据要进行大量的磁盘I/O操作,是非常时间,所以设计数据库索引结构需要首先考虑尽量的减少磁盘I/O操作
这里我们需要知道,从磁盘读取1B数据和1KB数据时间基本是一样的,我们就可以根据这个思路,让一次磁盘I/O的数据尽可能多,换句话也就是树节点存的数据尽可能多,这就是B树,B+树的设计原理
- B树
从上图可以知道,较AVl树,b树每个节点存储的结点更多键值和数据,基于这个特性,b树查找数据磁盘I/O次数会很少,查找效率也高很多,因为比较矮
b树的优点
- 优秀的索引效率,时间复杂度为O(h*lgn)h为树深度,n为每个节点关键子数
- 磁盘I/O次数少
- 支持范围查找
那B树和B+树有什么区别呢
5.B+树
- B+树的非叶子节点存放的是键值,不存放数据,而B树存放的键值和数据,所以B+一个节点可以存放多个键值,也就是多个索引,树就会更矮更肥,磁盘I/O次数更少
- B+树的叶子节点都用一个双向链表串联起来,便于范围查找