mysql索引:红黑树、B树、B+树

参考:
微信
知乎

此三者的主要应用是降低大数据量检索时的时间复杂度。

  • JDK中,HashMap、TreeMap都使用了红黑树。
  • MySql的索引,则使用了B+树。
    实际上二叉树(红黑树)的查询效率最高,而B+树则是n叉树,每个节点可以有多个关键字(通常是2-3个)。
    那么mysql索引为什么使用B+树呢?因为mysql的数据是存储在磁盘上的,每次取磁盘都是取一个内存页大小的数据量,而磁盘IO是最耗时的操作。如果采用二叉树来实现,在二叉树完美平衡的情况下,100万个数据的树高度至少也要20层。而有一半的数据分布在叶子节点也就是第20层上,那么这一半的数据的查询都要经历20次IO,假如每次IO需要10ms,则一条数据的查询就要200ms,假如某个方法要查询多个数据,那么查询时间加起来大概率是会超过人类能感觉的慢的响应时间了。
    B+树的每个节点中有多个关键字,节点中只存储用于索引的字段的关键字的值,不存储整条数据。
    假如每个节点的关键字个数是5,共有100万条数据的情况下,B+树的高度是8,但是由于树节点只存关键字、不存储数据,假如B+树的度数是6、每个节点占用86+58 ->100B内存,那么关键字个数为6、高度是8的树最多共有55987个节点,共5.6M,需要存储在两个磁盘页上,也就是说查询某条数据的磁盘位置需要IO两次,从磁盘中获取数据本身再IO一次,只需3次,相对于平衡二叉树来说,大大缩短了时间。

二叉查找树

对二叉树做中根遍历,数据是有序的,也称二叉排序树、二叉搜索树。

  • 每个节点最多有两个子节点
  • 节点的左子树中所有节点的值都小于这个节点的值,节点的右子树中所有节点的值都大于这个节点的值

平衡二叉树

每个节点的左右两个子树的高度差不大于1的二叉搜索树。

红黑树

红黑树是一种自平衡二叉查找树,又称为"对称二叉B树",它的统计性能要好于平衡二叉树。其典型的用途是实现关联数组。

特性

红黑树除了有二叉查找树的特性外,还有以下特性:

  • 每个节点都带有颜色属性
  • 根节点黑色、叶节点黑色、叶子节点必须是Nil(如果一个节点没有子节点,且不为Nil,则必须给它补上Nil节点)
  • 红色节点的两个子节点都是黑色
  • 从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点
  • 任一节点的左右子树,高的子树的高度不大于矮的子树的2倍(相较与AVL树-最大高度差不超过1-的规则,可以减少旋转次数,延迟为达到平衡的旋转,提高效率。)
自平衡

通过右旋、左旋、变色来实现。

  • 左旋:假设以节点P为轴做左旋操作,那么其右子节点R变更为根节点,其自身变更为R的左子节点,R原来的左子节点变更为P的右子节点在这里插入图片描述
  • 右旋:对节点P做右旋操作,则P的左子节点L变更为根节点,P变更为L的右子树,L原来的右子树变更为P的左子树。在这里插入图片描述
  • 变色:节点变颜色
    插入新的节点时,自平衡规则
    首先,插入的节点的颜色初值设为红色。
  • 无需调整的情况:当插入位置的父节点为黑色时
  • 变色即可实现平衡:父节点和叔父节点(父节点的兄弟节点,不分左右)都为红色时,只需变色(父、叔、祖父、自身节点都有可能需要变色)即可实现自平衡。空树插入时,插入的节点为根,只需将节点颜色变为黑色即可。
  • 旋转+变色:都是在父红、叔父黑色情况下,
    • 父节点为左子节点,插入节点为左子节点,即【左左】插入,需要祖父节点右旋+变色
    • 父节点为左子节点,插入节点为右子节点,即【左右】插入,需要父节点左旋+祖父节点右旋+变色
    • 父节点为右子节点,插入节点为左子节点,即【右左】插入,需要父节点右旋+祖父节点左旋+变色
    • 父节点为右子节点,插入节点为右子节点,即【右右】插入,需要祖父节点左旋+变色

删除节点

  • 待删除节点的左右子节点都为 null,删除时直接将该节点置为 null。
  • 待删除节点的左右子节点有一个有值,则用有值的节点替换该节点即可。
  • 待删除节点的左右子节点都不为 null,则找前驱或者后继,将前驱或者后继的值复制到该节点中,然后删除前驱或者后继
  • 节点删除后可能会造成红黑树的不平衡,这时我们需通过【变色】+【旋转】的方式来调整,使之平衡。
    红黑树插入调整示例

B树

红黑树是二叉树,当数据量大时,其高度必然增大。且每次插入或者删除都需要做平衡操作,很是消耗时间。

B树,也是自平衡的排序查找树,但是不要求子节点数目必须小于2。

  • 每个节点可以有最多M个子节点,M>=2,M即为B树的阶数
  • 每个节点中可以存储最多M个、最少M/2向上取整个key,一般为2-3个。
  • 所有叶子节点均在同一层
    在这里插入图片描述
B树的构建

B树的构建过程中每个节点中的关键字的个数都在动态改变。

因为其构建过程是:先对节点先扩充,当节点中关键字数量扩充到等于M时,再对其进行拆分,并将中间数升到父节点中去。

例如:定义一个5阶树(平衡5路查找树;),现在我们要把3、8、31、11、23、29、50、28 这些数字构建出一个5阶树出来;

遵循规则:

(1)节点拆分规则:当前是要组成一个5路查找树,那么此时m=5,关键字数必须<=5-1(这里关键字数>4就要进行节点拆分);当节点中关键字数大于4时,就将中间的关键字升为父节点的关键字(如果没有父节点,则创建一个父节点),然后创建此父节点的两个子节点,将中间关键字两边的关键字分别存储到这两个子节点中。

(2)排序规则:满足节点本身比左边节点大,比右边节点小的排序规则;

先插入 3、8、31、11
在这里插入图片描述
再插入23、29
在这里插入图片描述再插入50、28
在这里插入图片描述

删除节点

规则:

(1)节点合并规则:当前是要组成一个5路查找树,那么此时m=5,关键字数必须大于等于ceil(5/2)(这里关键字数<2就要进行节点合并);

(2)满足节点本身比左边节点大,比右边节点小的排序规则;

(3)关键字数小于二时先从子节点取,子节点没有符合条件时就向向父节点取,取中间值往父节点放;
在这里插入图片描述

B+树

B+树是B树的升级优化版,

  • 非叶子节点中的关键字不指向实际对象,也就是说B+树的非叶子节点不作存储作用,仅用作检索时的索引。
  • 叶子节点保存了所有父节点的关键字指向的对象,所有数据地址必须到叶子节点才能获取到,因此所有数据的比较次数都一样
  • 叶子节点中的所有关键字从小到大有序排列,每个节点的最后一个关键字记录了其右边的节点的第一个关键字的指针
  • 非叶子节点的关键字数=子节点数
    在这里插入图片描述
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值