索引底层实现原理
数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘块(对应索引树的节点),索引树越低,越矮胖,磁盘IO次数就少
MySQL支持两种索引,一种的B-树索引,一种是哈希索引,大家知道,B-树和哈希表在数据查询时的效率是非常高的。这里我们主要讨论一下MySQL InnoDB存储引擎,基于B-树(但实际上MySQL采用的是B+树结构)的索引结构。
B树
B-树是一种m阶平衡树,m一般是300-500(经验值),叶子节点都在同一层,由于每一个节点存储的数据量比较大,索引整个B-树的层数是非常低的,基本上不超过三层。
由于磁盘的读取也是按block块操作的(内存是按page页面操作的),因此B-树的节点大小一般设置为和磁盘块大小一致,这样一个B-树节点,就可以通过一次磁盘I/O把一个磁盘块的数据全部存储下来,所以当使用B-树存储索引的时候,磁盘I/O的操作次数是最少的(MySQL的读写效率,主要集中在磁盘I/O上)。
(这里盗下这位老哥的图哈哈哈)
从上图可以看到B-树存在的优缺点:
- 每个节点中有key,也有data,但是每一个节点的存储空间是有限的,如果data数据较大时会导致每个节点能存储的key的数据很小
- 当存储的数据量很大时同样会导致B-树的高度较大,磁盘IO次数花费增大,效率降低
- 索引和内容分散在整个B+树上,离根节点近搜索快,离根节点远搜索慢,花费的IO时间不平均
- 每一个非叶子结点不仅要存储key,还要存储data,一个节点能存放的索引key值的个数比只存储key值结点的个数要小得多
- 树不方便做范围搜索,整表遍历起来不方便
B+树
跟B树相比,B+树的叶子结点是一条链表,会将搜有的数据连接在一起,更加适合范围查询,并且每个非节点只存放key值,这样一个节点就能存放更多的key值,从而降低树的层高,叶子结点会复现非叶子结点的key
根据以上优点,所以Mysql最后采用B+树作为索引而没有采用B树
B树与B+树的对比
- B树的每一个节点,存了关键字和对应的数据地址,而B+树的非叶子节点只存关键字,不存数据地址。因此B+树的每一个非叶子节点存储的关键字是远远多于B-树的,B+树的叶子节点存放关键字和数据,因此,从树的高度上来说,B+树的高度要小于B-树,使用的磁盘I/O次数少,因此查询会更快一些
- B-树由于每个节点都存储关键字和数据,因此离根节点进的数据,查询的就快,离根节点远的数据,查询的就慢;B+树所有的数据都存在叶子节点上,因此在B+树上搜索关键字,找到对应数据的时间是比较平均的,没有快慢之分
- 在B-树上如果做区间查找,遍历的节点是非常多的;B+树所有叶子节点被连接成了有序链表结构,因此做整表遍历和区间查找是非常容易的