索引的实现原理
- 索引的实现原理
- 常见的数据结构对比
- 散列表
- 链表
- 二叉查找树
- 平衡二叉树
- B-树
- B+树
- B+Tree对比B-Tree
- 具体的索引实现
索引的实现原理
MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如B-Tree索引,B+Tree索引,哈希索引,全文索引等
常见的数据结构对比
散列表
散列表(也称哈希表)是根据关键码值(Key value)而直接进行访问的数据结构,它让码值经过哈希函数的转换映射到散列表对应的位置上,查找效率非常高。哈希索引就是基于散列表实现的,假设对名字建立了哈希索引,则查找过程
哈希索引主要用于memory引擎中
1、针对哈希索引,只有精确匹配索引所有列的查询才有效,比如在列(A,B)上建立了哈希索引,如果只查询数据列 A,则无法使用该索引
2、哈希索引并不是按照索引值顺序存存储的,所以也就无法用于排序,也就是说无法根据区间快速查找
3、哈希索引只包含哈希值和行指针,不存储字段值,所以不能使用索引中的值来避免读取行,不过,由于哈希索引多数是在内存中完成的,大部分情况下这一点不是问题
4、哈希索引只支持等值比较查询,包括 =,IN(),不支持任何范围的查找,如 age > 17
链表
双向链表支持顺序查找和逆序查找,索引是按照大小顺序进行存储的
什么是跳表?简单地说,跳表是在链表之上加上多层索引构成的。
跳表是能满足需求的,实际上它的结构已经和B+树非常接近了,只不过B+树是从平衡二叉查找树演化而来的而已
二叉查找树
图中的圆为二叉查找树的节点,节点中存储了键key和数据data。键对应user表中的id,数据对应user 表中的行数据。
二叉查找树的特点就是任何节点的左子节点的键值都小于当前节点的键值,右子节点的键值都大于当前节点的键值。顶端的节点称为根节点,没有子节点的节点称之为叶节点。
平衡二叉树
平衡二叉树又称 AVL 树,在满足二叉查找树特性的基础上,要求每个节点的左右子树的高度差不能超过 1
平衡二叉树保证了树的构造是平衡的,当插入或删除数据导致不满足平衡二叉树不平衡时,平衡二叉树会进行调整树上的节点来保持平衡。平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快。
B-树
因为内存的易失性。一般情况下都会选择将user表中的数据和索引存储在磁盘这种外围设备中。但是和内存相比,从磁盘中读取数据的速度会慢上百倍千倍甚至万倍,所以应当尽量减少从磁盘中读取数据的次数。另外从磁盘中读取数据时,都是按照磁盘块来读取的,并不是一条一条的读。如果能把尽量多的数据放进磁盘块中,那一次磁盘读取操作就会读取更多数据,那查找数据的时间也会大幅度降低。
如果用树这种数据结构作为索引的数据结构,那每查找一次数据就需要从磁盘中读取一个节点,也就是说的一个磁盘块。
二叉树的节点将会非常多,高度也会极其高,查找数据时也会进行很多次磁盘 IO,查找数据的效率将会极低
B 树相对于平衡二叉树,每个节点存储了更多的键值key和数据data,并且每个节点拥有更多的子节点,子节点的个数一般称为阶,例如B树为3阶B树,高度也会很低。基于这个特性,B树查找数据读取磁盘的次数将会很少,数据的查找效率也会比平衡二叉树高很多。
在BTree的机构下,就可以使用二分查找的查找方式,查找复杂度为【层高*log(结点数)】,一般来说树的高度是很小的,一般为3左右,因此BTree是一个非常高效的查找结构
B树的一些特点:
- 关键字集合分布在整颗树中
- 任何一个关键字出现且只出现在一个结点中
- 搜索有可能在非叶子结点结束
- 其搜索性能等价于在关键字全集内做一次二分查找
B树在插入删除新的数据记录会破坏B-Tree的性质,因为在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质
B+树
主要区别就是所有的节点值都在最后叶节点上用双向链表连接在了一起
但是二叉树不能使用,因为比对次数太多,所以使用多叉树以减少比对次数
B+Tree中的非叶子结点不存储数据,只存储键值
非叶子节点可以看成索引部分,节点中仅含有其子树(根节点)中的最大(或最小)关键字
B+Tree的叶子结点没有指针,所有键值都会出现在叶子结点上,且key存储的键值对应data数据的物理地址
B+Tree的每个非叶子节点由n个键值key和n个指针point组成
B+Tree对比B-Tree
磁盘读写代价更低:每个节点中的key个数越多,那么树的高度越小,需要I/O的次数越少,因此一般来说B+Tree比BTree更快,因为B+Tree的非叶节点中不存储data,就可以存储更多的key。
查询速度更稳定。由于B+Tree非叶子节点不存储数据data,因此所有的数据都要查询至叶子节点,而叶子节点的高度都是相同的,因此所有数据的查询速度都是一样的。
B+树的查找过程,与B树类似,只不过查找时,如果在非叶子节点上的关键字等于给定值,并不终止,而是继续沿着指针直到叶子节点位置。因此在B+树,不管查找成功与否,每次查找都是走了一条从根到叶子节点的路径。
B+树的特性如下:
所有关键字都存储在叶子节上,且链表中的关键字恰好是有序的。
非叶子节点相当于叶子节点的索引,叶子节点相当于是存储(关键字)数据的数据层。
更适合文件索引系统。
一般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上进行了优化,增加了顺序访问指针。
具体的索引实现
在MyISAM中,主索引和辅助索引Secondary key在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。
主键索引MyISAM引擎使用B+树作为索引结构,叶节点的data域存放的是数据记录的地址。
辅助索引:同样也是一棵B+树,data域保存数据记录的地址。因此,MyISAM中索引检索的算法为首先按照B+树搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。
MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分
innodb是索引组织表。在InnoDB中,表数据文件本身就是按B+树组织的一个索引结构(就是索引组织表),这棵树的叶节点data域保存了完整的数据记录。
因为InnoDB的数据文件本身要按主键聚集(聚集索引),所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整型。
辅助索引首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。