B树(B-树)
在计算机科学中,B树(英语:B-tree)是一种自平衡的树,能够保持数据有序。这种数据结构能够让查找数据、顺序访问、插入数据及删除的动作,都在对数时间内完成。B树,概括来说是一个一般化的二叉查找树(binary search tree),可以拥有多于2个子节点。与自平衡二叉查找树不同,B树为系统大块数据的读写操作做了优化。B树减少定位记录时所经历的中间过程,从而加快存取速度。B树这种数据结构可以用来描述外部存储。这种数据结构常被应用在数据库和文件系统的实现上。 --摘抄自百度百科
简单来说b树就是一颗多路平衡查找树,提高文件的查询效率而产生的。
下面是一颗高度为3的m阶B树:
比如需要搜索0008数据时,
- 只需要先将0007-0011加载到内存读取;
- 然后定位到数据在0007-0011;
- 然后加载数据0009,定位到数据在小于0009;
- 最后定位到数据0008。
只需要3次检索就可以定位到数据。
我们将一个key和其对应的data称为一个记录。但为了方便描述,除非特别说明,后续文中就用key来代替(key, value)键值对这个整体。在数据库中我们将B树(和B+树)作为索引结构,可以加快查询速速,此时B树中的key就表示键,而data表示了这个键对应的条目在硬盘上的逻辑地址。
B+树
B+树是一种树数据结构,通常用于数据库和操作系统的文件系统中。B+树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+树元素自底向上插入,这与二叉树恰好相反。 --摘抄自百度百科
通过上图可以看出B+树相对于B树多出了下面叶子节点的单向链表。正是B+树将所有节点通过单向链表有序的排列后可以很方便的范围上查找数据,所以mysql数据的MyISAM与InnoDB引擎都采用了B+树的数据结构,而没有使用B树的数据结构。
下图是InnoDB引擎的索引的数据结构,主键索引叶子节点保存了完整的数据,索引结构和数据存储文件是没有分开的。而MyISAM引擎叶子节点存储了,指向数据地址的指针,索引结构和数据存储文件是分开的。
假设一个int类型的索引大小是8byte, 加上指向下一个索引页号的指针 6byte。每次加在数据到内存的页面大小是16k,那么16 * 1024 /(8 + 6) = 1170.一行数据大小1kb,那么一个三层的B+树可以存储的数据是 1170 * 1170 * 16 = 2190 2400,可以存储两千多万的数据。
索引设计总结:
根据B+树数据结构,我们在设计和使用索引的时候可以适当优化:
- 设计索引时,尽量用小的数据类型,那么一次页面加载读取的索引数量就会更多,那么搜索效率就会提高;
- 索引类型尽量使用整形自增,如下图插入中间数据0003,此时导致0001和0004页分裂,从影响数据查询效率;
- 在范围查询的时候,搜索字段尽量加上索引。
B+树也是多路平衡查找树,其与B树的区别主要在于:
1. B树中每个节点(包括叶节点和非叶节点)都存储真实的数据,B+树中只有叶子节点存 储真实的数据,非叶节点只存储键。
在MySQL中,这里所说的真实数据,可能是行的全部数据(如Innodb的聚簇索引),也可能只是行的主键(如Innodb的辅助索引),或者是行所在的地址(如MyIsam的非聚簇索引)。
2. B树中一条记录只会出现一次,不会重复出现,而B+树的键则可能重复重现——一定会 在叶节点出现,也可能在非叶节点重复出现。
3. B+树的叶节点之间通过双向链表链接。
B树中的非叶节点,记录数比子节点个数少1;而B+树中记录数与子节点个数相同。
由此,B+树与B树相比,有以下优势。
更少的IO次数、更适于范围查询、更稳定的查询效率。
LSM树
LSM树(Log-Structured-Merge-Tree)的名字往往会给初识者一个错误的印象,事实上,LSM树并不像B+树、红黑树一样是一颗严格的树状数据结构,它其实是一种存储结构,目前HBase,LevelDB,RocksDB这些NoSQL存储都是采用的LSM树。
LSM树的核心特点是利用顺序写来提高写性能,但因为分层(此处分层是指的分为内存和文件两部分)的设计会稍微降低读性能,但是通过牺牲小部分读性能换来高性能写,使得LSM树成为非常流行的存储结构。
流程:
- 读取数据时会读取多个cxxx中的数据结构,内存中没有就会从磁盘中读取;
- 将数据划分为基准数据和增量数据,修改、新增的数据顺序记录日志然后到达内存,当达到一个阈值将会批量合并写入到磁盘中,从而提高效率。