目录
一、Hash
1.1 数据库索引为什么不用Hash结构
1.2 Hash结构的适用情况
二、二叉搜索树
三、AVL树
四、B树
五、B+树
5.1 B+ 树和 B 树的差异
5.2 为什么用B+树不用B树?
一、Hash
Hash本身是一个散列函数,可以帮助我们提升数据检索的效率。
Hash算法是通过某种确定的算法,将输入转变为输出。相同的输入一定得到相同的输出。
假设我们要验证两个文件是否相同,只需要对比它们用hash函数计算的结果。
采用Hash进行检索的效率很高,只需检索一次就能找到数据,而B+树需要从上往下查找。单从效率上说,Hash比B+树快。效率O(1).
Hash函数计算每个记录的哈希值,把它们映射到Hash表的不同位置上。
上图中哈希函数h有可能将两个不同的关键字映射到相同的位置,这叫做 碰撞 ,在数据库中一般采用 链接法 来解决。在链接法中,将散列到同一槽位的元素放在一个链表中,如下图所示:
1.1 数据库索引为什么不用Hash结构
等/不等/IN (等值查询)查询,如果进行范围查询,检索效率会退化为O(n),而树形仍然能保持O(log2n)的效率。
无序的,Order By 时还需要对数据重新排序。
3.对于联合索引的情况,Hash值是将键合并之后计算的,但Hash值相同不代表数据就相同。
等值查询,Hash索引效率高,但如果索引列的重复值很多,效率就会降低。因为遇到Hash冲突时,需要遍历桶中的指针比较,很耗时。
1.2 Hash结构的适用情况
等值查询的场景。比如用在键值型(K-V)数据库中,例如Redis。
InnoDB本身不支持Hash索引,但提供自适应Hash索引。如果某个数据经常被访问,满足一定条件时就会将这个数据页的地址存到hash表中。这样可以显著提高检索效率。
二、二叉搜索树
二叉搜索树的结构:对于某个节点,其左子节点比它小,右子节点比它大。
树的高度 ,需要把 原来“瘦高”的树结构变的“矮胖”,树的每层的分叉越多越好。
然而有时候二叉搜索树的深度会很大,例如{5,22,23,34,77,89,91}
这时树就退化成链表了。。。
三、AVL树
平衡二叉搜索树。它会自动调整树的结构,保证树的两边子树的高度差不超过1,两个左右子树都是一颗平衡二叉树。时间复杂度O(log2n)。
但是如果节点太多了,那它的深度也就增加了,每访问一次节点就要进行一次IO操作。
所以我们要把树从瘦高变为矮胖。
四、B树
多路平衡查找树,每个节点可以包含N个子节点。非叶子节点包含关键字和子节点的指针。
A、B,3个指针P1、P2、P3。P1指向主键比A小的磁盘块,P1指向主键大小介于A、B的磁盘块,P3指向主键比B大的磁盘块。
在 B 树的搜索过程中,我们比较的次数并不少,但如果把数据读取出来然后在内存中进行比 较,这个时间就是可以忽略不计的。而读取磁盘块本身需要进行 I/O 操作,消耗的时间比在内存中进行比较所需要的时间要多,是数据查找用时的重要因素。 B 树相比于平衡二叉树来说磁盘 I/O 操作要少 , 在数据查询中比平衡二叉树效率要高。所以 只要树的高度足够低,IO次数足够少,就可以提高查询性能 。
五、B+树
B+树也是一种多路搜索树。更适合文件索引系统。
5.1 B+ 树和 B 树的差异
1. B+树中,有 k 个孩子的节点就有 k 个关键字,孩子数量 = 关键字数;而 B 树中,孩子数量 = 关键字数 +1。
2. B+树中非叶子节点的关键字也会同时存在在子节点中,是子节点中所有关键字的最大(或最 小),而B树则不会。
3. B+树非叶子节点仅用于索引,不保存数据记录,跟记录有关的信息都放在叶子节点中。而 B 树中, 非叶子节点既保存索引,也保存数据记录 。
所有关键字都在叶子节点出现,叶子节点本身按照关键字的大小从小到大顺序链接,构成一个有序链表。B树叶子节点间好像没联系。
5.2 为什么用B+树不用B树?
查询效率稳定,每次必须访问到叶子节点才能找到对应数据。而B树非叶子节点也会存数据。
查询效率更高。通常B+树比B树的深度低,磁盘IO更少。
3.B+树叶子节点间构成双向链表,范围查找时可利用指针查找,效率高。B树要用中序遍历。