<span>027-B树(二)</span>
https://cloud.tencent.com/developer/article/1441681
不知道你有没有这种感觉,那些所谓的数据结构和算法,在日常开发工作中很少用到或者几乎不曾用到,可能只是在每次换工作准备面试的时候才会捡起来学习学习。
那我希望今天这篇文章能让你对数据结构的具体应用能有个初步的概念,就从我们每天都在用的 mysql 数据库说起吧。
今天这个标题,严格来说其实是不正确的,我在前面的文章中有这么解释过:执行一条sql语句都经历了什么?
首先,mysql 主要是由 server 层和存储层两部分构成的。server 层主要包括连接器、查询缓存,分析器、优化器、执行器。存储层主要是用来存储和查询数据的,常用的存储引擎有 InnoDB、MyISAM,MySQL 5.5.5版本后使用 InnoDB 作为默认存储引擎。
这篇文章我们主要讨论 mysql 的存储层,不同的存储引擎其底层的数据结构是不一样的,我们这里就以默认的 InnoDB 为例,所以严格来说应该是 InnoDB 为啥要选择 B+ 树这种数据结构来存储数据。
在文章正式开始之前,你先要知道 mysql 中的 InnoDB 在底层是采用 B+ 树这种数据结构来存储数据的。你先记住就好了,下面我们再来一步一步解释为什么。
- 几种常见的数据结构
首先你要知道,mysql 的索引主要是为了提高查询效率的,那一定得找一个合适的数据结构来存储数据,哈希表、数组、二叉搜索树这三种常见的数据结构都可以提高查询效率。
- 哈希表
哈希表就是一种以键值对来存储数据的结构,你可以通过一个 key 就可以很快的查询出对用的 value 值。哈希表主要是利用了数组的随机访问特性,实现思想主要是通过一个哈希函数把 key 转换成一个哈希值,这个哈希值就对应数组中的某个下标。
但是由于哈希表是无序的,区间查询效率会非常的慢,所以哈希表通常只用于查询单个值。
- 有序数组
数组就好说了,数组具有连续性和随机访问特性,因此数组都能很高效的进行单个等值查询和区间查询,但是 mysql 不仅仅是查询数据,还会有插入和删除数据的操作。
在有序数组中插入或删除一个数据会需要批量移动数组中其他数据,这是一个不小的消耗,影响性能。因此有序数组适合处理静态数据,比如一些过往的不会再修改的数据。
在这里你可能会问,既然哈希表其实也是利用了数组的特性,那有了数组为啥还需要哈希表呢。是因为数组下标 key 只能是数字,而哈希表可以支持字符串 key,哈希函数可以把这个 key 转换成一个数组下标。
同时,不同的 key 如果通过哈希函数转换成了相同的数组下标,这就会造成冲突,在哈希表中一般会通过再拉出一个链表来保存这个冲突的值。
关于哈希表这里就不再多说了,后面的文章再详细解释哈希表的原理以及相关应用。
- 二叉搜索树
注意,二叉搜索树和二叉树不一样,二叉树是指每个节点的左儿子小于父节点,父节点又小于右儿子,即二叉搜索树的中序遍历就是一个有序序列。
由于索引不仅仅是存在内存中,还会存储在硬盘中,因此就会涉及到 IO 性能了,就要求树的高度不能太高。实际上 B+ 树就是通过二叉搜索树推演改进的,我将在后面的文章再详细解释这个改进过程。
- 小结
哈希表适合等值查询,由于是无序的,区间查询会很慢。
有序数组适合等值和区间查询,但是数组具有连续性,插入和删除操作都可能需要移动其他元素。
二叉搜索树由于树的高度,区间查询需要中序遍历,都会导致查询效率很慢。
注意,在一些文章中经常会把 B+ 树说成 B 树或者 B-tree,这其实是错误的,B 树和 B+ 是两种不同的树,B+ 树是 B 树的一个优化,后面的文章我会再详细解释这个优化过程。
而且 B- 树其实也就是 B 树,这个符号并不是加减中的减号,并不是所谓的 "B 减树",只是一个连接符号而已。