先看一下二叉树的示意图:
二叉查找树是每个节点最多有两个子树的数据结构,通常子树被称为左子树或右子树。二叉查找树的重要性质是,对于树中的每个节点x,它的左子树的任意节点的值均小于x,右子树的任意节点的值都大于x。如果用二叉查找树来作为我们的索引,确实能够提升查询效率。这里需要我们注意的是,我们说的索引的存储块和我们之前说的数据库的最小存储单位——块或页,实际上并非一一对应,只是为了方便我们的理解,先将其一一对应起来。每个存储块,存储的是关键字,还有指向子树的指针。
像上图左边的树,它不仅仅是二叉树,还是平衡二叉树,那什么是平衡二叉树呢?就是它的任意一个节点的左子树和右子树,它的高度均不超过1。
二叉查找树查找用的是二分查找,比如说,我们要搜6,6比5要大,我们就找右子树,找到7,7比6大,所以我们又会去查7的左子树,这样我们就能定位到6了。因为是对半搜索,所以它的时间复杂度是O(logn),因此其查询效率是非常高的。但是它也有缺点,首先咱们的数据库的数据可能面临着新增和删除,比如删除了2和6,新增了11和13,结果就变成右图的线性二叉树,那么它的时间复杂度就变成了O(n),大大降低了查询效率,有的人可能会说,我们可以利用树的旋转特性来保证这棵树是平衡二叉树,这样其时间复杂度会维持在O(logn)就可以了。这样确实解决了第一个问题,但是它还会有第二个问题,咱们之前说了,影响程序运行速度的瓶颈在IO,如果我们假定这些索引块都在磁盘中,拿刚刚的检索来讲,去找6,会发生一次IO,将这个根的数据读入到我们的内存中,那之后呢,再发生一次IO,将7读入进来,紧接着再发生一次IO,读入了6,即检索深度增加1,就会发生一次IO,咱们的平衡二叉树也好,红黑树也罢,每个节点最多只能有两个孩子,而咱们的数据块会非常多,因此为了组织起这些数据块,咱们树的深度就会很深很深,IO的次数也会很多,这样数据一多,其检索性能比咱们之前说的全表扫描要慢很多,根本就没法满足我们的优化查询的需求。那咱们还有什么办法,既降低查询的时间复杂度,又降低IO的次数呢?主要就是让树变得矮一些,数据呢每个节点能存储的数据多一些,这个时候,咱们就想到B+Tree了。请看下一章。