数据库查询是数据库的最主要功能之一。最基本的查询算法就是顺序查找,这种复杂度为O(n)的算法在数据量很大时是性能很差的。

1.B树索引和B+树索引

目前大部分数据库系统和文件系统都采用B-Tree或者B+Tree作为索引结构。

B-Tree

为了描述B-Tree,首先定义一条数据记录为一个二元组[key,data],key为记录的键值,对于不同的数据记录,key是互不相同的。data为数据记录除key外的数据。
由于B-Tree树的特性,在B-Tree中按照key检索数据的算法就为:

  • 首先从根节点进行二分查找,如果找到则返回对应节点的data
  • 否则就对相应区间的指针指向的节点递归查找,直到找到节点或者找到null
带有顺序访问指针的B+Tree

一般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上做了优化,增加了顺序访问指针

mysql数据库结构对比工具 mysql和数据结构_mysql数据库结构对比工具


如上图所示:在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能

B-/+索引的性能分析

索引以索引文件的形式存储在磁盘中(因为索引文件也有可能很大,所以将索引文件存放在内存中不现实,也没有必要),这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数

我们需要知道的是,从磁盘中读取数据时,都是按照磁盘块来读取的,并不是一条一条的读,如果我们能把尽量多的数据放进磁盘块中,那一次磁盘读取操作就会读取更多的数据,那我们查找数据的时间也会大幅度降低
所以在B-Tree的设计中,运用了计算机的局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入了

在B树的结构中:

mysql数据库结构对比工具 mysql和数据结构_键值_02


图中的每个节点称为页,页就是我们上面说的磁盘块,在MySQL中数据读取的基本单位都是页

在B-Tree树中,每个节点存储了更多的键值(key)和数据(data),并且每个节点拥有更多的子节点,子节点的个数一般称为阶,基于这个特性,B树查找数据读取磁盘的次数将会很少,数据的查找效率也会高很多

B+树

B+树是对B树的进一步优化。

mysql数据库结构对比工具 mysql和数据结构_mysql数据库结构对比工具_03


相比较B树:

  • B+树非叶子节点是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据(如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树,在B+树中,阶数就等于键值个数)就更大,那么整颗数就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数又会再次减少,数据查询的效率也会更快

1.3 B+Tree性质

  • n颗子树的节点包含n个关键字,不用来保存数据而是用来保存数据的索引
  • 所有的叶子节点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子节点本身依关键字的大小自小而大顺序链接
  • 所有非终端节点可以看成是索引部分,节点中仅含有其子树中的最大(最小)关键字
  • B+树中,数据对象的插入和删除仅在叶节点上进行
  • B+树有两个头指针,一个是树的根节点,一个是最小关键码的叶节点