数据库索引的底层数据结构的学习
要想了解数据库索引的底层原理,我们就得先了解树的数据结构,树中最典型的是二叉树,再往下学习是特殊的二叉树-平衡二叉树,再到b-树,最后到b+树,一步一步了解数据库的底层原理
二叉树
拿排序进行说明,给一个无序的数组,将第一个数放到a的位置,将下一个数与第一个数进行比较,如果比第一个数小,就放在数组的左边,假如放在b的位置,然后再进一个数,进来的数如果比a处的数小,到a的左子树,然后与b处的数进行比较,如果比b处的数小,放在b的左子树处,即c处。这种数据结构,具有链式数据结构的优点,搜索查询方便,但是添加或者删除数据比较麻烦。
平衡二叉树
这是一个二叉树,但是他的排列结构是二叉树,但是也可以理解成一个链表了。
平衡二叉树,是一种特殊的二叉树,他满足二叉树的基本的特点,如上面,二叉树还有一个特别的特点,平衡二叉树的左右子树之间的高度差不能超过1,如果超过1就把上一个子树作为节点,进行左旋
这棵树始终满足平衡二叉树的几个特性而保持平衡!这样我们的树也不会退化为线性链表了!我们需要查找一个数的时候就能沿着树根一直往下找,这样的查找效率和二分法查找是一样的呢!
B-树
上面的满足下面的规则的平衡二叉树就是B—树
一个m阶的B-树的特性:
1、每个结点最多m个子结点。
2、除了根结点和叶子结点外,每个结点最少有m/2(向上取整)个子结点。
3、如果根结点不是叶子结点,那根结点至少包含两个子结点。
4、所有的叶子结点都位于同一层。
5、每个结点都包含k个元素(关键字),这里m/2≤k<m,这里m 2向下取整。
6、每个元素(关键字)字左结点的值,都小于或等于该元素(关键字)。右结点的值都大于或等于该元素(关键字)。
下面以一个 [0,1,2,3,4,5,6,7]的数组插入一颗3阶的B-Tree为例:
遍历的方式(查找24):
平衡二叉树和B-树之间的对比
从这个流程我们能看出,B-Tree的查询效率好像也并不比平衡二叉树高。但是查询所经过的结点数量要 少很多,也就意味着要少很多次的磁盘IO,这对性能的提升是很大的。
前面对B-Tree操作的图我们能看出来,元素就是类似1、2、3这样的数值,但是数据库的数据都是一条条的数据,如果某个数据库以B-Tree的数据结构存储数据,那数据怎么存放的呢?我们看下一张图
普通的B-Tree的结点中,元素就是一个个的数字。但是上图中,我们把元素部分拆分成了key-data的形式,key就是数据的主键,data就是具体的数据。这样我们在找一条数的时候,就沿着根结点往下找就ok了,效率是比较高的。
B+Tree
B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构。B+Tree与B-Tree的结构很像,但是也有几个自己的特性:
1、所有的非叶子节点只存储关键字信息。
2、所有卫星数据(具体数据)都存在叶子结点中。
3、所有的叶子结点中包含了全部元素的信息。
4、所有叶子节点之间都有一个链指针。
如果上面B-Tree的图变成B+Tree ,那应该如下:
1、非叶子结点上已经只有key信息了,满足上面第1点特性!
2、所有叶子结点下面都有一个data区域,满足上面第2点特性!
3、非叶子结点的数据在叶子结点上都能找到,如根结点的元素4、8在最底层的叶子结点上也能找到, 满足上面第3点特性!
4、注意图中叶子结点之间的箭头,满足满足上面第4点特性!
数据库的底层是b-树 or b+树
在讲这两种数据结构在数据库中的选择之前,我们还需要了解的一个知识点是操作系统从磁盘读取数据到内存是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是 需要什么取什么。
即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理 论依据是计算机科学中著名的局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。预读的长度一般为页(page)的整倍数。
页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k)。
讨论:
1、B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高 。
2、由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。
3、由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比 B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。
鉴于以上的比较,所以在常用的关系型数据库中,都是选择B+Tree的数据结构来存储数据!