数据库索引为何用B+树实现?

为何大多数数据库索引都使用B+树来实现呢?这涉及到数据结构、操做系统、计算机存储层次结构等等复杂的理论知识,可是不用担忧,这篇文章20分钟以后就会给你答案。数据库

这篇文章是一系列数据库索引文章中的最后一篇,这个系列包括了下面四篇文章:编程

  1. 数据库索引是什么?新华字典来帮你 —— 理解缓存

  2. 数据库索引融会贯通 —— 深刻数据结构

  3. 20分钟数据库索引设计实战 —— 实战post

  4. 数据库索引为何用B+树实现? —— 扩展优化

这一系列涵盖了数据库索引从理论到实践的一系列知识,一站式解决了从理解到融会贯通的全过程,相信每一篇文章均可以给你带来更深刻的体验。操作系统

为何使用B+树?

你们在数学课上必定据说过一个例子,在一堆已经排好序的数字当中找出一个特定的数字的最好办法是一种叫“二分查找”的方式。具体的过程就是先找到这些数字中间的那一个数,而后比较目标数字是大于仍是小于这个数;而后根据结果继续在前一半或者后一半数字中继续查找。设计

这就相似于数据结构中的二叉树,二叉树就是以下的一种结构,树中的每一个节点至多能够有两个子节点,而B+树每一个节点则能够有N个子节点。3d

image.png

这里就不具体展开讲解二叉树了,咱们只须要知道,平衡的二叉树是内存中查询效率最高的一种数据结构就能够了。指针

可是目前经常使用的数据库中,绝大多数的索引都是使用B+树实现的。那么为何明明是二叉树查询效率最高,数据库中却恰恰要使用B+树而不是二叉树来实现索引呢?

计算机存储层次结构

image.png

计算机中的存储结构分为好几个部分,从上到下大体能够分为寄存器、高速缓存、主存储器、辅助存储器。其中主存储器,也就是咱们常说的内存;辅助存储器也被称为外存,比较常见的就是磁盘、SSD,能够用来保存文件。在这个存储结构中,每一级存储的速度都比上一级慢不少,因此程序访问越上层存储中的数据,速度就会越快。

有过编程经验的小伙伴都知道,程序运行过程当中操做的基本都是内存,对外存中数据的访问每每须要写一些文件的读取和写入代码才能实现。这正是由于CPU的计算速度比存储的I/O速度(输入/输出速度)快不少所作的优化,由于CPU在每次计算完成以后就须要等待下一批的数据进入,这个等待的时间越短,计算机运行得越快。

因此对于数据库索引来讲,由于数据量很大,因此基本都是保存在外存中的,这样的话数据库读取一个索引节点的成本就很是大了。在数据量同样大的状况下,咱们能够知道,B+树的单个节点中包含的值个数越多那么树中须要的节点总数就会越少,这样查询一次数据须要访问的节点数就更少了。

若是你对B+树还不熟悉,能够到这篇文章中找到答案——数据库索引融会贯通

若是咱们把二叉树看作是特殊的B+树(每一个节点只有一个值和先后两个指针的B+树),那么就能够得出结论:**由于B+树的节点中包含的值个数(多个值)比二叉树(1个值)更多,因此在B+树中查询所须要的节点数就更少。**那么若是每次读取的成本是同样的话,由于总成本=读取次数*单次读取成本,咱们就能够证实B+树的查询成本就比二叉树小得多了。

节点读取成本

可是咱们知道,读取更多数据确定会须要更大的成本,那么为何数据库索引使用B+树仍是会比二叉树更好呢?这就须要一些更高深的操做系统知识来解释了。

在现代的操做系统中,把数据从外存读到内存所使用的单位通常被称为“页”,每次读取数据都须要读入整数个的“页”,而不能读入半页或者0.8页。一页的大小由操做系统决定,常见的页大小通常为4KB=4096字节。因此无论咱们是要读取1字节仍是2KB,最后都是须要读入一个完整的4KB大小的页的,那么一个节点的读取成本就取决于须要读入的页数。

在这样的状况下,若是一个节点的大小小于一页的大小,那么就会有一部分时间花在读取咱们根本不须要的数据上(节点以外的数据),二叉树在这方面就会浪费不少时间;而若是一个节点的大小大于一页,哪怕是一页的整数倍,那咱们也可能在一个节点的中间就找到了咱们须要的指针进入了下一级的节点,这样这个指针后面的数据都白白读取了,若是不须要这些数据可能咱们就能够少读几页了。

因此,综上所述,数据库索引使用节点大小刚好等于操做系统一页大小的B+树来实现是效率最高的选择。