阅读 341

【重学算法】B树与B+树

  1. B树

B树也称B-树,它是一棵多路平衡查找树。B 树其实就是一棵每个节点的子节点个数不能小于 m/2 的 m 叉树。B树的定义如下:

每个节点最多有m-1个关键字(可以存有的键值对)。 根节点最少可以只有1个关键字。 非根节点至少有m/2个关键字。 每个节点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。 所有叶子节点都位于同一层,或者说根节点到每个叶子节点的长度都相同。 每个节点都存有索引和数据,也就是对应的key和value。 描述一颗B树时需要指定它的阶数,阶数表示了一个节点最多有多少个孩子节点,一般用字母m表示阶数。其中,根节点的关键字数量范围:1 <= k <= m-1,非根节点的关键字数量范围:m/2 <= k <= m-1。

  1. B+树

按照我的理解,B+树是B树+有序链表。下面我们来看一下B+树与B树的异同点。B+树与B树的相同点:

根节点至少一个元素 非根节点元素范围:m/2 <= k <= m-1 不同点:

B+树有两种类型的节点:索引节点和叶子结点。索引节点就是非叶子节点,内部节点不存储数据,只存储索引,数据都存储在叶子节点。 每个叶子结点都存有相邻叶子结点的指针,叶子结点本身依关键字的大小自小而大顺序链接。 父节点存有右孩子的第一个元素的索引。 索引结点中的key都按照从小到大的顺序排列,对于索引结点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子结点中的记录也按照key的大小排列。  

  1. B+树相对于B树的优势

所有的查询都要查找到叶子节点,查询性能是稳定的;而B树,每个节点都可以查找到数据,所以不稳定。 所有的叶子节点形成了一个有序链表,更加便于查找。(通过链表将叶子节点串联在一起便于区间查找)  

  1. 为什么数据库底层数据结构用B+树?

B 树与 B+ 树的最大区别就是,B 树可以在非叶结点中存储数据,但是 B+ 树的所有数据其实都存储在叶子节点中。

B+ 树因为所有的数据行都存储在叶节点中,而这些叶节点可以通过指针依次按顺序连接,当我们在如下所示的 B+ 树遍历数据时可以直接在多个子节点之间进行跳转,这样能够节省大量的磁盘 I/O 时间,也不需要在不同层级的节点之间对数据进行拼接和排序;通过一个 B+ 树最左侧的叶子节点,我们可以像链表一样遍历整个树中的全部数据,我们也可以引入双向链表保证倒序遍历时的性能。

  1. 哈希索引、有序数组索引、二叉树索引、B树索引的优缺点

a. 哈希索引

优点:因为哈希索引是根据索引字段计算位置,所以它的插入和根据key的查找会很快。

缺点:使用哈希索引做范围查询速度会很慢。如果要根据范围查找数据,就必须全表扫描索引。

适合场景:适用于等值查询的场景,比如Redis或者其他的NoSQL数据库。

b. 有序数组索引

优点:有序数组因为存入的数据已经是排好序的,所以根据等值查到和范围查到都比较快。

缺点:如果我们需要往数组中间插入一个值或者删除中间的某个值,那就需要挪动这个值所在位置后面的所有元素,成本比较高。

适合场景:适用于静态存储引擎,存储不会再插入、删除的数据。

c. 二叉树索引

优点:查询效率高

缺点:树的高度高。因为索引不止存在于内存中,也要写到磁盘里。如果一个二叉树高度为20,我们查询某个用户信息就要访问20次磁盘,这个效率是非常低的。

适用场景:适用于表数据比较少的引擎。

为了减少树的高度,也就是减少对磁盘的访问,数据库索引就使用M叉树取代了二叉树。

d. B树索引

优点:B 树能够在非叶节点中存储数据,减少空间存储数据。

缺点:在非叶子节点存储数据这也导致在查询连续数据时可能会带来更多的随机 I/O,而 B+ 树的所有叶节点可以通过指针相互连接,能够减少顺序遍历时产生的额外随机 I/O。

 

  1. InnoDB中主键索引和非主键索引的区别

MySQL 默认的存储引擎 InnoDB 会使用 B+ 树来存储数据,无论是主键索引(聚簇索引)还是辅助索引(二级索引)最终都会使用 B+ 树来存储数据,其中前者在表中会以 <id, row> 的方式存储,而后者会以 <index, id> 的方式进行存储,后者根据主键找到id后再查找一次,即回表。

文章分类
后端
文章标签