B+树
一、文章背景
引用维基百科的定义:’'在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。"
B+树
是一种数据结构,但是因为它常常是出现在文件存储系统和数据库系统中,所以大多数讨论到B+树
是基于它作为数据库索引数据结构,所以本文结合MySQL
索引探讨一下B+树
。本文参考: 平衡查找树之B树
二、内容概要
- 简要说明一下
B树
和B+树
的数据结构。 - 探讨
B树
和B+树
两种数据结构在从磁盘读取时的差异。 - 结合
MySQL
的组合索引,分析组合索引的最左原则,不满足最左原则查询一定不走索引吗?
三、详细内容
3.1 简要介绍B树
和B+树
B树
,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。与自平衡二叉树不同,B树
为系统最优化大块数据的读和写操作。B-Tree
算法减少定位记录时所经历的中间过程,从而加快存取速度。
B树
看做是对2-3查找树
的一种扩展,即他允许每个节点有M-1个子节点(M 为树的阶,也叫度)。
- 根节点至少有两个子节点
- 每个节点有M-1个key,并且以升序排列
- 位于M-1和M key的子节点的值位于M-1 和M key对应的Value之间
- 其它节点至少有M/2个子节点
B+树
,是对B树
的一种变形树,他与B树
的差异在于:
- 有K个子节点的节点必然有K个关键码。
- 非叶子节点仅具有索引的作用,具体的值或者说是具体的信息放在叶子节点中。
- 树的所有叶子节点构成一个有序链表,可以按照关键码的次序遍历全局记录。
两中数据结构的差异也就是B+树的优势:
- 因为非叶子节点不存储具体信息,所以能够存放更多的key。数据的存放更加紧密,具有更好地空间局部性。因此访问叶子节点上关联的数据具有更好的缓存命中率。
B+树
的叶子节点是相链的,是有序链表结构,因此遍历B+树只需要先行遍历一遍叶子节点。而B树
则需要遍历整个树。
3.2 B树
和B+树
两种数据结构在从磁盘读取时的差异。
这里要讲一个预读的概念,由于存储介质的特性,磁盘本身存取就比主存慢得多,再加上机械运动耗费,因此为了提高效率,要尽量减少磁盘I/O,减少读写操作。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。理论依据:局部性理论
,当一个数据被用到时,其附近的数据也通常会马上被使用。
预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。
文件系统及数据库系统的设计者利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:
因为在磁盘读取时,每次读取的数据量大小是固定的,因为B树
的非叶节点存储了指针信息,所以每次读取B树结构的数据时,所能够获取的索引信息较少。相反,因为B+树
的非叶子节点之存储索引,所以拿到的key相对多,即B+树的阶比较大,同时B+树的高度更低,更扁平。而高度决定了I/O次数,所以B+树
结构能够减少I/O次数。
3.3 结合MySQL
的组合索引,分析组合索引的最左原则,不满足最左原则查询一定不走索引吗?
先简单介绍一下组合索引,例:创建组合索引(a,bc),那么相当于创建了(a),(a,b),(a,b,c)三个索引.
由于b+树的结构,索引有了最左原则
那么一定要遵循最左原则吗?不遵循最左原则的SQL
语句,一定不走索引,全文搜索吗?
select a from table_a where b =1 and c =2;
使用explain
命令,得出,该语句type
属性为index
同样走了索引,不同的是,index表示查询索引时,是遍历索引而不是特殊算法。
但是,如果是
select * from table_a where b =1 and c =2;
即:在查询结果列时,如果有列名不是组合索引中的,那么,explain命令得出,type属性为All