数据库的索引,依赖于B+树。
之前仅简单了解使用B+ 树,是因为查找速度快,查找仅仅取决于树的高度。但是更加详细的内容,以及为什么使用B+树,而不是B树家族的其他数据结构,则并不清楚。因而详细研究一番。
二叉搜索树
二叉搜索树,数据结构书中有详细阐述,也是B树家族的基础。
- 所有非叶子结点至多拥有两个子结点;
- 所有结点存储一个关键字;
- 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;
这种结构,非常有利于搜索,但是值得注意的是,当二叉树的结构不够平衡的时候,搜索的性能会受到极大影响。二叉搜索树的查询速度,取决于树的高度H。
实际情况中使用的二叉搜索树,基本上都是添加了平衡算法的。
平衡二叉树的平衡原理:插入数据或者删除数据时候进行旋转,保证二叉树的平衡
平衡二叉搜索树(AVL树)
平衡二叉搜索树,在二叉搜索树的基础上增加了平衡性
- 所有非叶子结点至多拥有两个子结点;
- 所有结点存储一个关键字;
- 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;
- 左子树和右子树的深度之差的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树
B树(B-树,平衡多路查找树)
B树,相较于平衡二叉搜索树的主要差别为,去掉至多两个子树的限制。
- 非叶结点内,值按照左小右大的原则
- 非叶结点,(M/2)向上取整<子结点数<=M (M>=2)
- 结点如果有k个子结点,则有k-1个值
- 叶子结点都为同一水平,叶子结点非空
这样的数据结构,可以显著降低查询的耗时,树的高度为h,则查询时间复杂度为O(h)
B树的结点插入规则:(1)结点拆分规则:M路查找树,这里关键字数>=M就要进行结点拆分;(2)结点拆分:将当前结点中间数字提取出来合并入父结点,当前结点剩余数字拆分为左右两部分,合并后如果父结点关键字数>=M,则继续进行拆分和合并。
B树的结点删除规则:(1)结点合并规则:结点内关键字数必须大于等于(M/2向上取整);(2)关键字数小于等于(M/2向上取整)时先从子节点取,子节点没有符合条件时就向向父节点取,取中间值往父节点放;如果父结点或者子结点被取数后导致大小不足,则循环进行合并与处理
B+树
B+树为相对于B树的优化,查询速度更稳定,更加充分的利用了结点内的空间。
- B+数的非叶子结点内不存储数据,仅存储索引
- 叶子结点保存所有数据内容,每次查找都需要相同的次数
- 叶子结点有序,左结点存放右节点的指针
- 非叶结点的关键字数=子结点数(mysql实现方式)/子结点数-1
B+树的优点是:层级更少,查询速度更稳定,天然具备排序功能,全节点遍历更快。
B*树
B*树是B+树的变种
- 非根和非叶子结点增加指向兄弟的指针
- 非叶子结点关键字个数至少为(2/3)*M向上取整
B*树分配新结点的概率比B+树要低,空间使用率更高
当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针;