赞
踩
目录
在MySQL的学习中,我们了解到了索引的知识,而关于MySQL索引背后的数据结构,我们在这里进行学习.
首先,我们要了解到的是,MySQL的索引用到的数据结构为B+树.
使用B+树是因为,在数据量大的时候,内存不够用,大部分数据只能存放在磁盘上,只有需要的数据才加载到内存中。一般而言内存访问的时间约为 50 ns,而磁盘在 10 ms 左右。速度相差了近 5 个数量级,磁盘读取时间远远超过了数据在内存中比较的时间。这说明程序大部分时间会阻塞在磁盘 IO 上。这也正是我们采取B树的原因,普通的二叉树,红黑树等是没法满足这类需求的.所以我们采用新的存储方式.
二叉树是二分树,多分树是二叉树的推广。多分树主要适用于静态的索引数据文件,在插入和删除的时候需要把插入位置之后的每个记录都要向后移动,从而导致增加新的索引项和索引页块,需要对外存上的页块进行大量的调整。因此对于经常需要插入和删除的动态索引顺序文件,使用多分树并不合适,需要采用动态索引结构,即B树和B+树。
B树的出现是为了弥补不同的存储级别之间的访问速度上的巨大差异,实现高效的 I/O。平衡二叉树的查找效率是非常高的,并可以通过降低树的深度来提高查找的效率。但是当数据量非常大,树的存储的元素数量是有限的,这样会导致二叉查找树结构由于树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下。另外数据量过大会导致内存空间不够容纳平衡二叉树所有结点的情况。B树是解决这个问题的很好的结构。
一棵m阶B树是一棵平衡的m路搜索树,它或者是空树,或者是满足下列性质的树:
由图可知,当节点的子树多了,叶子节点的个数就多了,说明可以保存的key值也变多了
这也就意味着,在保存key值相同个数的条件下,B树的高度相对于二叉搜索树就要低很多.这样的优势非常明显:磁盘 IO 的次数将大大减少!
- Data* BTreeSearch(Root *node, Key key)
- {
- Data* data;
-
- if(root == NULL)
- return NULL;
- data = BinarySearch(node);
- if(data->key == key)
- {
- return data;
- }else{
- node = ReadDisk(data->next);
- BTreeSearch(node, key);
- }
- }
B+树是应文件系统所需而产生的B树的变形树,那么可能一定会想到,既然有了B树,又出一个B+树,那B+树必然是有很多优点的。
B+树在B树上又做出了改进.B+树是B-树的变体,也是一种多路搜索树, 它与 B- 树的不同之处在于:
B+树是B树上的一个修改或者改版:
1.B+树的每个节点可以存储N个key,N个key同时也划分出了N个区间(B树是N+1个区间)
2.B+树中每个节点中key的值,都会在子节点中也出现,并且是该子节点的最大值
3.B+树的叶子结点,是首尾相连的,类似于一个链表
4.B+树的叶子结点是完整的数据集合,只会在叶子结点这里存储每一行的数据,而不是叶子结点本身,只需要存储key值即可
B+树的优势:
1.一个节点保存更多的key,最终树的相对高度是更低的,查询的时候减少了IO次数(这点和B树相同)
2.所有的查询最后都会落到叶子节点上(查询任何一个数据,经过的IO访问次数是一样的)确保了稳定性,能够对程序的执行效率有更准确的评估.
3.B+树的所有的叶子结点可以构成链表,方便进行范围查询.
4.由于所有的数据都在叶子节点上,非叶子结点指存储key,这样非叶子节点占用的空间很小,(可能在内存中缓存或缓存一部分),又进一步减少了IO的次数
补充:B树的范围查找用的是中序遍历,而B+树用的是在链表上遍历。
B树 | B+树 |
---|---|
有m颗子树的节点中含有 m-1 个关键码 | 有m颗子树的节点中含有 m 个关键码 |
B树中非叶子节点的关键码与叶子结点的关键码均不重复,它们共同构成全部的索引信息 | 所有的叶子结点中包含了完整的索引信息,包括指向含有这些关键字记录的指针,中间节点每个元素不保存数据,只用来索引 |
B 树的非叶子节点包含需要查找的有效信息 | 所有的非叶子节点可以看成是高层索引, 结点中仅含有其子树根结点中最大(或最小)关键字 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。