《数据库系统内 幕》B树的变体

简介: 《数据库系统内 幕》B树的变体

章六


B树的变体共同点:树结构、通过分裂合并实现平衡,以及查找和删除算法。

变体的区别:并发性、磁盘页表示、同级节点之间的链接和维护进程这些细节方面的不同。

写放大的问题:一个B树页后续更新可能需要每次更新时更新其磁盘驻留页副本。

空间放大问题:保留额外空间实现更新。


写时复制B树(COW)


这个变体是由于锁的等待时间而延申出来的结构。

实例:LMDB是一个使用写时复制的存储引擎。它不需要页缓存、预写日志、生成检查点或压实操作。

这是一个直接通过内存映射来满足读写操作,不用额外的缓存。

写时复制的过程:在更新时,找到目标子节点,将从根节点到目标子节点的路径中每个分支节点都被复制。更新所传播到的节点被修改,而其余节点将保持不变。

1.png

实现思路:在对数据进行操作(增、删、改)之前,先把所有可能操作到的层级(所有祖先节点)数据块都拷贝一份出来(C’,B’,A’),后面的修改就在这份拷贝后的数据块上做修改,修改完之后再把这些数据块写入到磁盘文件新的位置上,这时候磁盘中就有两份数据,一份是修改之前的,一份是修改之后的,从修改之前的根节点开始遍历,可以读到所有修改之前的旧版数据,从修改之后的新根节点开始遍历,可以读到所有修改之后的新版数据。 从不同的根节点进去可以读取到不同版本的数据,这个CoW既保证了读写安全,也带有很优雅的数据备份功能(数据快照)。

同时当旧的根进行的读操作结束后,其页就会被回收,并且可以被重新使用。尽管保留很短的时间,还是一个占用更多的空间。(缺点)

MVCC全称Multi-Version Concurrency Control,即多版本并发控制,主要是为了提高数据库的并发性能


惰性B树


惰性B树降低了更新的成本,使用更轻量级的内存结构来缓冲并延迟传播更新。

实例:MongoDB中的存储引擎WiredTiger使用了惰性B树。

更新被保存到更新缓冲区中,在读取中访问更新缓存区,与原始磁盘页中内容合并,返回新数据。当刷写到磁盘上时,更新缓冲区内容与页内容协调然后保存在磁盘上。

优点:页更新和结构修改操作(分裂、合并)由后台线程执行,读写进程不必等待。

从单个节点缓冲更新延申到子树中,可以为每个子树附加用于批量操作得更新缓冲区。此时更新缓冲区将跟踪子树顶部节点及后代节点所执行得所有操作,称为惰性自适应树(LA树)。

2.png

在插入数据记录时,先加入根节点更新缓存区,在填满后我们将这些更改复制然后传播到较低层缓冲区,依次递归继续,直至叶节点。直到更新到达叶节点时,将在叶子层进行批量的插入、更新和删除操作,同时将所有更改应用于树的内容及结构。

优点:因为在更新子节点的过程中会产生分裂与合并操作可以传播到高层,所以这是一个减少磁盘访问的次数的方法,更加高效。


FD树


前面是通过创建辅助缓冲区来缓冲对单个节点或节点组的更新。还有另一种方法是通过仅追加存储和合并过程将不同节点更新归并在一起,将这种追加操作用于索引的例子叫做闪存盘树(Flash Disk Tree)。

FD树最重要的是分段级联思想,来维护层之间的指针。因为仅追加存储以及合并,将不同节点更新归并到一起,这意味这更新无需定位目标节点,只是单纯的追加操作。

3.png


FD树由一个小的,可变的头部树和多个不可变的有序段构成。随机IO产生时,会把更新缓冲在头部的小型B树中,一旦头部树被填满,就会把内容转移到不可变的有序段中,如果有序段超过阈值,就会和下一层合并。

FD树不在原地更新页,并且可能在几个层上存在相同键的数据记录,所以FD树使用墓碑来进行删除,类似一个标记,表示相应数据被删除,当墓碑被传到最底层的时候,就可以被丢弃了。因为此时可以保证没有需要它遮蔽的数据了。


分层级联的思想


比较简单,这个思想为了降低定位每个节点的成本,因为它可以帮助你在最接近的匹配项来进行搜索。

可以通过三个有序数组的例子了解这个思想。


Z = [12,24,32,34,39]

J = [22,25,28,30,35]

L = [11,16,24,26,30]


为了简化搜索,将下层数组中每隔几个元素(例子选择隔一个)就将一个元素拉到上层数组中来弥补元素间的间隔。


Z = [12,24,25,30,32,34,39]

J = [16,22,25,26,28,30,35]

L = [11,16,24,26,30]


把这些被挑出来的作为指针,由高层指向低层,则建立了级联结构。


Bw树


Bw树是通过仅追加存储来对不同节点进行批量更新解决这写放大与空间放大还有并发的问题。

每个节点由一个链表构成,链表末尾是基节点,其余是增量节点,增量节点表示更新插入,删除。并使用到了内存数据结构,该结构允许单个CAS操作在节点间建立指针,这种方法称Bw树。

CAS(V,E,N)操作是比较并交换,包含三个参数,内存地址V,E是预期值,N是新值。如果V上存放的值等于期望的值A,则将地址上的值赋为新值E,如果不等则自旋。


缓存无关B树


一个缓存无关B树由一个静态B树和一个打包的数组结构组成。静态B树使用van Emde Boas布局构建。在中间层的边上将树分裂,然后用类似方法分裂每个子树,最后得到大小为根号N的子树。这种布局的关键思想是,任何递归树都存储在一个连续内存块中。逻辑上,可以看到节点紧密形成树结构,底层存储可以看到树节点的内存和磁盘布局。


4.png

读不进去了,放一张杨舒宇的照片,哇,好好看,努力努力!


相关文章
|
7月前
|
存储 关系型数据库 MySQL
索引大战:探秘InnoDB数据库中B树和Hash索引的优劣
索引大战:探秘InnoDB数据库中B树和Hash索引的优劣
71 0
|
13天前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因?
B+树优化了数据存储和查询效率,数据仅存于叶子节点,便于区间查询和遍历,磁盘读写成本低,查询效率稳定,特别适合数据库索引及范围查询。
30 6
|
24天前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因
B+树相较于B树,在数据存储、磁盘读写、查询效率及范围查询方面更具优势。数据仅存于叶子节点,便于高效遍历和区间查询;内部节点不含数据,提高缓存命中率;查询路径固定,效率稳定;特别适合数据库索引使用。
27 1
|
7月前
|
存储 关系型数据库 MySQL
【MySQL 解析】数据库为什么使用B+树而不是B树
【1月更文挑战第11天】【MySQL 解析】数据库为什么使用B+树而不是B树
|
7月前
|
存储 关系型数据库 MySQL
【MySQL】数据库中为什么使用B+树不用B树
【MySQL】数据库中为什么使用B+树不用B树
|
7月前
|
SQL 关系型数据库 数据库
【后端面经】【数据库与MySQL】SQL优化:如何发现SQL中的问题?
【4月更文挑战第12天】数据库优化涉及硬件升级、操作系统调整、服务器/引擎优化和SQL优化。SQL优化目标是减少磁盘IO和内存/CPU消耗。`EXPLAIN`命令用于检查SQL执行计划,关注`type`、`possible_keys`、`key`、`rows`和`filtered`字段。设计索引时考虑外键、频繁出现在`where`、`order by`和关联查询中的列,以及区分度高的列。大数据表改结构需谨慎,可能需要停机、低峰期变更或新建表。面试中应准备SQL优化案例,如覆盖索引、优化`order by`、`count`和索引提示。优化分页查询时避免大偏移量,可利用上一批的最大ID进行限制。
118 3
|
7月前
|
存储 关系型数据库 MySQL
【后端面经】【数据库与MySQL】为什么MySQL用B+树而不用B树?-01
【4月更文挑战第10天】B+树是一种多叉树,用于数据库索引,其特征包括叶子节点存储数据并用链表串联,非叶子节点仅存关键字。由于较低的高度和链表结构,B+树提供高效查询和范围查询。索引分类有聚簇(叶子节点存储数据)和非聚簇,以及覆盖、唯一、前缀、联合、全文和哈希索引。聚簇索引如主键索引,非聚簇索引叶子节点存储主键。覆盖索引可避免回表,提高性能。查询遵循最左匹配原则,优化SQL应选取所需列并考虑常见查询。
49 4
|
7月前
|
存储 关系型数据库 MySQL
【后端面经】【数据库与MySQL】为什么MySQL用B+树而不用B树?-02
【4月更文挑战第11天】数据库索引使用规则:`AND`用`OR`不用,正用反不用,范围中断。索引带来空间和内存代价,包括额外磁盘空间、内存占用和数据修改时的维护成本。面试中可能涉及B+树、聚簇索引、覆盖索引等知识点。MySQL采用B+树,因其利于范围查询和内存效率。数据库不使用索引可能因`!=`、`LIKE`、字段区分度低、特殊表达式或全表扫描更快。索引与NULL值处理在不同数据库中有差异,MySQL允许NULL在索引中的使用。
50 3
|
存储 数据库 索引
数据库索引采用B+树不采用B树的原因
磁盘块读写效率更高:B+树相比于B树,在磁盘块的读写上具有更好的性能。B+树内部的非叶子节点只存储键值信息,而不包含具体的数据记录,这使得每个磁盘块能够存储更多的键值对。同时,由于叶子节点间使用链表进行连接,可以通过顺序读取的方式快速扫描整个索引。因此,B+树在进行磁盘块的读写操作时,具有更高的效率。
120 0