二叉树:
二叉树(Binary Tree)是指至多只有两个子节点的树形数据结构,没有父节点的节点为根节点,没有子节点的节点称为叶子节点。
二叉搜索树就是任何节点的左子节点小于当前节点键值,右子节点大于当前节点键值。
如下图的二叉搜索树,我们最多只需要⌈ l o g ( n ) ⌉ ⌈log(n)⌉⌈log(n)⌉即三次即可匹配到数据,而线性查找的话最坏情况需要n nn次才可匹配到。
但是二叉树可能会退化成链表的情况,如下图所示,这样就相当于全部扫描了,导致效率不高,为了解决这个问题,需要确保二叉树一直保持平衡,即平衡二叉树。
平衡二叉树:
平衡二叉树(AVL树)在满足二叉树特性的基础上,要求每一个节点的左右子树高度差不能超过1。它保证了树构造的一个平衡,当插入或删除数据导致不平衡时,会进行节点调整来保持平衡(具体算法略),确保查找效率。
平衡二叉树的一个节点对应一个键值和数据,我们每次查找数据就需要从磁盘中读取一个节点,也就是我们说的磁盘块,一个节点对应一个磁盘块。当存储海量数据时,树的节点会非常多,会进行很多次的磁盘I/O,查找效率仍是极低的。这就需要一个单节点能存储多个键值和数据的一种平衡树了。
B树:
B树(Blance Tree)就是可以单节点存储多键值和数据的平衡树,每一个节点我们称之为页(Page),即一页数据。每个节点存储了更多键值和数据,把键值和数据都放在一个页当中,并且每个节点拥有了更多子节点,子节点的个数一般称为阶。B树在查找数据读取磁盘的次数也就大大减少,查找效率比AVL高很多。
如下图的3阶B树中,查找id=42的数据。首先在第一页里判断42键值大于39,根据指针P3找到第4页,再进行比较,小于键值45,又根据指针P1找到第9页,发现匹配有匹配的键值42,即找到相应数据。
B+树:
B+树是对B树的进一步优化。简单说就是B+树的非叶子节点是不存储数据的,仅存放键值。之所以这样做,是因为数据库中页的大小是固定的(InnoDB默认16KB),如果不存储数据,就可以存储更多键值,节点个数就越大,查找数据进行磁盘I/O次数进一步减少。
另外B+树的阶数是等于它的键值数量的,如果一个节点存储1000键值的话,那么只需要三层就可存储10亿数据,所以一般查找10亿数据只需两次磁盘I/O即可(妙啊)。
同时B+树叶节点的数据是按顺序进行排列的,所以B+树适合范围查找、排序查找和分组查找等(B各数据分散在节点上,相对就困难),也就是为什么MySQL采用B+树索引的原因了。