经常用于查询的数据结构

既然MySQL的索引是为了简化查询的,所以我们简单的看一下可用于查询的数据结构有哪些。数据结构只做简单的介绍,如果某种数据结构不懂的,还得另行学习。(或者我有时间补充?)

1.二叉排序树

二叉排序树又叫二叉搜索树(BST),顾名思义首先是一颗二叉树,其中的每一个节点都表示一个对象。一般每个节点除了存数据之外,还应该有指向左孩子,右孩子以及父亲节点的指针。一个简单的
二叉排序树结构如下:

2.平衡二叉树&&红黑树

平衡二叉树(AVL树),是带有平衡条件的二叉查找树,其左右子树的高度差的绝对值相差不超过1。所以当我们执行插入或者删除时,如果不满足平衡二叉树的条件,就得进行旋转操作来保持平衡。具体的旋转有左旋,右旋等等。但是旋转操作非常的耗时,付出的代价比我们查找获取的效益要大,所以我们基本不用平衡二叉树。AVL树适合用于插入与删除次数比较少,但查找多的情况。
对于插入和删除次数比较多的情况下,我们不方便使用AVL树。这时,我们可以选择红黑树,也叫弱平衡二叉树,在每个节点增加一个存储位表示节点的颜色,可以是红或黑(非红即黑)。通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍,所以在同样的插入删除操作,红黑树的旋转次数少于AVL树。

3.B树&&B+树

B树,全名为多路平衡查找树。和平衡二叉树的区别在于B树是一颗多叉树,常说的B-树就是B树。B树所有的节点关键字是从小到大排序。以m阶B树简单的介绍一下数据结构。
  1. 每个节点最多只有m个子节点。
  2. 每个非叶子节点(除了根)具有至少⌈ m/2⌉子节点。
  3. 如果根不是叶节点,则根至少有两个子节点。
  4. 具有k个子节点的非叶节点包含k -1个键。
  5. 所有叶子都出现在同一水平,没有任何信息(高度一致)。
 
 
一个非叶子结点如果有k1,k2,k3...kn个值。那么这个节点有n+1个节点,每个节点分别存小于k1,大于k1小于k2....大于kn,所以一共k+1个节点,方便查找。
如上图所示,由于是多叉树,所以树的深度比较低,查询的速度比较快。比如我们要查找55这个数,首先先进根节点,30<55<80,所以我们选择第二个节点进去。50<55<60,所以我们还是查找该子树的第二个节点,刚好叶子结点55,查到了返回即可。
B+树是在B树的基础上进行一些优化,B+树的非叶子节点不保存关键字记录的指针,只进行数据索引,这样使得B+树每个非叶子节点所能保存的关键字大大增加;B+树叶子节点保存了父节点的所有关键字记录的指针,所有数据地址必须要到叶子节点才能获取到。所以每次数据查询的次数都一样;B+树叶子节点的关键字从小到大有序排列,左边结尾数据都会保存右边节点开始数据的指针。

为什么MySQL索引用B+树

本文只说InnoDB引擎的索引结构。
了解了一些便于查询的数据结构,我们其实可以发现这几种数据结构的优缺点。首先是AVL 树和红黑树这些二叉树结构的数据结构可以达到最高的查询效率,但是这些结构都是在内存中使用才会选择的数据结构。而数据库的索引是要存在磁盘中的,磁盘读取的特点是操作系统读写磁盘的基本单位是扇区,而文件系统的基本单位是簇(Cluster)。也就是说,磁盘读写有一个最少内容的限制,即使我们只需要这个簇上的一个字节的内容,我们也要把这个簇上的内容都读完。所以那些二叉树的数据结构每个子节点存的不能够填满整个簇的内容,从而造成了读取的浪费。而且存储同样大小的内容。B树和B+树由于子节点多,所以深度会相对比较浅。深度就代表着磁盘的IO次数。所以我们索引不会采取二叉树之类的来实现。
B+树的非叶子节点相比于B树并不存储数据,所以B+树的非叶子节点的大小是要小于B树的,所以B+树的IO效率要高于B树。同时实际业务中数据库中select数据,不一定只选一条,很多时候会选中多条,比如按照id进行排序后选100条。如果是多条的话,B+树需要做局部的中序遍历,可能要跨层访问。而B+树由于所有数据都在叶子结点不用跨层,同时由于有链表结构,只需要找到首尾,通过链表就能把所有数据取出来了。所以索引一般都使用B+树。

总结

B+树很适合用作索引所以并不是所有的索引都是用的B+树。比如在MongoDB 中的索引数据结构就是B树,也和它的特性有关。MySQL一些场景下也可以用hash表来建立索引。无论如何还是那句话数据结构的选取要看业务场景,只要熟悉每种数据结构的优劣,就不难理解索引选取数据结构的考虑了。