索引设计是应用程序设计和开发的重要组成,关系型数据库使用最为频繁的是 B+ 树索引,其中 B 表示的是平衡(balance)。
下面从分析数据结构和算法入手分析 B+ 树索引。
二叉查找树和平衡二叉树
B+ 树是由二叉查找树,再由二叉平衡树,B 树演化而来,在分析 B+ 树之前先从二叉树开始了解。二叉查找树的基本思想是二分查找,二分查找(binary search)亦称折半查找,其思想是将一组数据按序排列,在查找过程中以查找区间中点位置为比较对象跳跃查找,不断折半缩小查找区间。
二叉查找树是一种经典数据结构,上图显示的是一棵二叉查找树,在二叉查找树中,左子树的键值总是小于根的键值,右子树的键值总是大于根的键值。这意味着可以通过中序遍历得到有序的键值输出,即:2、3、5、6、7、8。通过这棵二叉查找树进行查找其实本质就是二分查找,如查找键值为 5 的记录,查找顺序是 根节点->左子树(3)->右子树(5)
,一共查找三次。
二叉查找树可以任意构造,根据节点插入顺序,相同的一组键值也可能展现出其他的结构,如上图,平均查找次数 (1+2+3+4+5+5)/6=3.16 次,而顺序查找平均查找次数为 (1+2+3+4+5+6)/6=3.3 次,二者效率很接近,但是二叉树带来了更高的复杂度。极端情况,二叉树甚至可能退化成链表,这就无法起到二分查找的作用。
唯一应对二叉查找树退化问题,产生了平衡二叉树,又称 AVL 树。平衡二叉树是在二叉查找树的基础上满足任何节点的两个子树的高度最大差为 1。平衡二叉树具有很好的查询效率,但过于严格的平衡条件导致维护一棵平衡二叉树的代价十分大,通常需要一次或多次旋转来得到插入或更新后树的平衡。
B+ 树
B 树和 B+ 树都是平衡查找树,而且是多路平衡查找树,即每个节点的子树可能超过两个。
一棵 M 阶 B 树,是一颗 M 路平衡查找树或者是一个空树(注:M阶代表一个树节点最多有多少个查找路径),满足以下条件:
所有节点键值按递增排列,并遵循左小右大原则;
每个非叶子节点(除了根)的子节点数量 <= ceil(m/2) 个且 < M 个(注:ceil() 是个朝正无穷方向取整的函数 如 ceil(1.1) 结果为 2);
非叶子节点的键值数量是其子节点数量 - 1;
所有叶子节点均在同一层,叶子节点除了包含了关键字和关键字记录的指针外也有指向其子节点的指针,只不过其指针地址都为 null。
上图是一个 3 阶 B 树,B 树的的性能总是等价于二分查找(与 M值 无关),也就没有 AVL 树平衡的问题。
B+ 树是对 B 树的改进,和 B 树不同在于:
非叶子结点的子树指针与关键字个数相同;
非叶子结点的子树指针 P[i],指向关键字值属于 [K[i], K[i+1]) 的子树(B-树是开区间);
所有的非叶子节点都只保存索引,不保存数据&#