在这里需要说明下的是,BTree的结构里每个节点包含了索引值和表记录的信息,我们可以按照Map集合这样理解:key=索引,value=表记录,如下图所示:
2. 优点:
BTree的结构可以弥补红黑树的缺点,解决数据量过大时整棵树高度过大的问题,相同的数据量只需要更少的层,相同的深度可以存储更多的数据,查找效率更高。
3. 缺点
在查询单条数据是很快的,但是如果范围查询的话,BTree结构每次都需要从根节点查询一遍,会影响效率,因此在实际应用时采用的是B+Tree
5. B+Tree(MySQL索引的真正存储结构)在介绍B+Tree之前,我们先来看下面两个问题:
1. 为什么要对BTree继续做优化?
要解答这个疑问需要先了解BTree每个节点结构(上面已经说明)和MySQL数据库它是如何读取索引数据的,索引和表数据在不使用的时候是存储在文件中的,也就是磁盘,
当我们执行查询操作时DBMS(数据库管理系统)首先会先从内存中查找,如果找到直接使用,如果找不到则从磁盘文件中读取;操作系统储存数据的最小单位是页(page),
一页假设是4K大小(由操作系统决定),对内存和磁盘读取数据是按一页的整数倍读取的。
这里我们假设数据库一次IO操作就读取1页4K的数据,再假设图中圈起来的元素就是一个大节点,内含多个小节点的索引和数据,其大小是10MB,
那么我们要从磁盘中读取完整个大节点需要进行 10M / 4K = 2500次IO操作,这样就可以看出如果大节点数据总量越大,需要执行的IO操作越多,花费的时间也越长,
因此为了提高性能,数据库会建议我们一个大节点只存储一页4K大小的数据,这里的数据包含了索引和表记录,另外我们还能计算出树的度Degree应该设置成多大才合理:
Degree = 内存页大小(4K) / 单个索引值字节大小;
进一步分析,索引值的大小相对于整条记录的大小是很小的,如果我们需要查找的数据刚好是在最后,那么前面遍历过的节点中存储的记录数据是不是对我们来说是没用的,
它会占用比索引大得多的空间,导致我们一个大节点里能遍历的索引数量大大减少,需要向下继续遍历的几率就更大,花费更多时间查找,那么有没有办法可以优化呢?看下一个问题。
2. 相对于BTree,B+Tree做了哪些优化?
B+Tree存储结构,只有叶子节点存储数据
新的B+树结构没有在所有的节点里存储记录数据,而是只在最下层的叶子节点存储,上层的所有非叶子节点只存放索引信息,
这样的结构可以让单个节点存放下更多索引值,增大度Degree的值,提高命中目标记录的几率。
这种结构会在上层非叶子节点存储一部分冗余数据,但是这样的缺点都是可以容忍的,因为冗余的都是索引数据,不会对内存造成大的负担。
B+Tree特性:
非叶子节点不存储data,只存储key(索引值),可增大度
叶子节点不存储指针
顺序访问指针,提高区间访问的性能
每个叶子节点都指向下一个叶子节点
这点优化有什么用呢?我们直接看下面的B+Tree结构,如果我们进行范围查找where id > 4的记录,我们只需要先找到id = 4的记录后自然就能通过叶子节点间的双向指针方便地查询出大于4的所有记录。