数据引擎--LSM树与B+数

本文深入探讨LSM树概念,对比传统B+树的性能瓶颈,阐述LSM树如何通过牺牲部分读性能来显著提高写性能。通过内存中构建有序小树并定期flush到磁盘,实现高效数据存储与检索。关键点包括WAL(WriteAheadLog)机制、memstore与storefile的作用,以及compact操作的必要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LSM树是HBase里非常有创意的一种数据结构,它和传统的B+树不太一样,下面先说说B+树。

1 B+树

相信大家对B+树已经非常的熟悉,比如Oracle的普通索引就是采用B+树的方式,下面是一个B+树的例子:



根节点和枝节点很简单,分别记录每个叶子节点的最小值,并用一个指针指向叶子节点。

叶子节点里每个键值都指向真正的数据块(如Oracle里的RowID),每个叶子节点都有前指针和后指针,这是为了做范围查询时,叶子节点间可以直接跳转,从而避免再去回溯至枝和跟节点。

B+树最大的性能问题是会产生大量的随机IO,随着新数据的插入,叶子节点会慢慢分裂,逻辑上连续的叶子节点在物理上往往不连续,甚至分离的很远,但做范围查询时,会产生大量读随机IO。

对于大量的随机写也一样,举一个插入key跨度很大的例子,如7->1000->3->2000 ... 新插入的数据存储在磁盘上相隔很远,会产生大量的随机写IO.

从上面可以看出,低下的磁盘寻道速度严重影响性能(近些年来,磁盘寻道速度的发展几乎处于停滞的状态)。

2 LSM树

为了克服B+树的弱点,HBase引入了LSM树的概念,即Log-Structured Merge-Trees。

为了更好的说明LSM树的原理,下面举个比较极端的例子:

现在假设有1000个节点的随机key,对于磁盘来说,肯定是把这1000个节点顺序写入磁盘最快,但是这样一来,读就悲剧了,因为key在磁盘中完全无序,每次读取都要全扫描;

那么,为了让读性能尽量高,数据在磁盘中必须得有序,这就是B+树的原理,但是写就悲剧了,因为会产生大量的随机IO,磁盘寻道速度跟不上。

LSM树本质上就是在读写之间取得平衡,和B+树相比,它牺牲了部分读性能,用来大幅提高写性能

它的原理是把一颗大树拆分成N棵小树, 它首先写入到内存中(内存没有寻道速度的问题,随机写的性能得到大幅提升),在内存中构建一颗有序小树,随着小树越来越大,内存的小树会flush到磁盘上。当读时,由于不知道数据在哪棵小树上,因此必须遍历所有的小树,但在每颗小树内部数据是有序的。



以上就是LSM树最本质的原理,有了原理,再看具体的技术就很简单了。

1)首先说说为什么要有WAL(Write Ahead Log),很简单,因为数据是先写到内存中,如果断电,内存中的数据会丢失,因此为了保护内存中的数据,需要在磁盘上先记录logfile,当内存中的数据flush到磁盘上时,就可以抛弃相应的Logfile。

2)什么是memstore, storefile?很简单,上面说过,LSM树就是一堆小树,在内存中的小树即memstore,每次flush,内存中的memstore变成磁盘上一个新的storefile。

3)为什么会有compact?很简单,随着小树越来越多,读的性能会越来越差,因此需要在适当的时候,对磁盘中的小树进行merge,多棵小树变成一颗大树。

<think>嗯,用户现在想了解MySQL中B+数据结构的工作原理应用场景。从对话历史看,用户之前询问过Spring事务传播行为,说明他对数据库底层机制有一定兴趣,可能是后端开发人员或数据库学习者。 用户提供的三个引用都聚焦在B+的特性MySQL索引实现上。引用1提到B+数据库索引、文件系统等领域的广泛应用;引用2强调MySQL为每个索引维护独立的B+;引用3则说明B+只在叶子节点存储数据的特点。这些信息高度相关,需要重点整合。 用户的核心诉求很明确:既要理解B+的技术原理(如多级索引、平衡机制),也要知道它在MySQL中的具体作用(如加速查询)。可能还有未明说的深层需求,比如为索引优化或数据库选型提供理论依据。 需要从三个层次展开回答: 1)基础原理:B+的结构特性(多叉、叶子链表、非叶节点仅存指针) 2)MySQL适配:InnoDB如何利用B+实现聚簇索引/二级索引 3)性能优势:对比B、哈希索引等方案的优劣 特别要注意技术细节的准确性。比如必须强调B+叶子节点包含所有数据记录(聚簇索引),而不仅仅是键值;范围查询优化依赖叶子节点的双向链表结构;高通常控制在3-4层等关键点。 用户似乎偏好结构化表达,上次对事务传播行为的表格总结反馈良好。这次同样采用分层说明:先图示化展示B+层级,再用表格对比不同索引类型,最后通过SQL示例说明索引效果。学表达要严格遵循LaTeX格式,如节点容量公式$m/2 \leq children \leq m$需用$包裹。 可能延伸的问题是B+在分布式数据库中的变体(如LSM),以及索引维护的成本分析(页分裂、重建索引等)。这些作为补充问题列在最后,供用户深度探索。</think>以下是 MySQL 中 B+ 数据结构的工作原理及其在数据库中的核心作用详解: --- ### 一、B+ 核心结构原理 #### 1. **层级结构** - **多叉平衡**:每个节点可包含多个子节点(通常百),显著降低- **节点容量公式**: 设阶为 $m$,则: - 根节点子节点:$2 \leq children \leq m$ - 非根节点:$\lceil m/2 \rceil \leq children \leq m$ #### 2. **节点类型** | 节点类型 | 存储内容 | 特性 | |--------------|----------------------------------|--------------------------| | **非叶节点** | 索引键(Key) + 子节点指针 | 不存储实际数据[^3] | | **叶节点** | 索引键(Key) +数据/主键指针 | 通过双向链表连接[^1] | #### 3. **数据存储规则** ```plaintext [根节点] / \ [非叶节点] [非叶节点] / \ / \ [叶节点] [叶节点] [叶节点] [叶节点] ← 双向链表连接 |k1|k2| |k3|k4| |k5|k6| |k7|k8| ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 数据/指针 数据/指针 ... ``` - **聚簇索引**:叶节点直接存储行数据(如 InnoDB 主键索引)[^2] - **二级索引**:叶节点存储主键值,需回表查询[^2] --- ### 二、B+ 在 MySQL 中的核心作用 #### 1. **高效查询优化** - **范围查询**: 叶节点双向链表支持高效顺序扫描(如 `WHERE id BETWEEN 100 AND 200`) - **等值查询**: 时间复杂度 $O(\log_m N)$($m$ 为阶,$N$ 为数据量) - **全表扫描**: 直接遍历叶节点链表,避免回溯 #### 2. **索引管理机制 - **自动平衡**:插入/删除时通过节点分裂($\uparrow$)合并($\downarrow$)维持平衡 - **空间利用率**:节点填充率 ≥ 50%(优于 B ) #### 3. **存储引擎的协作 | 存储引擎 | 索引实现 | 特点 | |------------|------------------|--------------------------| | **InnoDB** | 聚簇索引(B+) | 数据文件即索引文件[^2] | | **MyISAM** | 非聚簇索引(B+) | 数据索引分离存储 | --- ### 三、B+ vs B 的关键优势 | 特性 | B+ | B | |---------------------|--------------------------------|--------------------------| | **数据存储位置** | 仅叶节点存储数据 | 所有节点均可存储数据 | | **范围查询效率** | ⭐⭐⭐⭐ (双向链表优化) | ⭐⭐ (需中序遍历) | | **高控制** | 更低(相同数据量) | 更高 | | **磁盘 I/O** | 更少(非叶节点纯索引) | 更多 | | **缓存命中率** | 更高(非叶节点可缓存更多键值) | 较低 | > 💡 **示例场景**: > 查询 `SELECT * FROM users WHERE age > 30`: > - B+ :定位首个 age=30 的叶节点 → 沿链表向后扫描 > - B :需反复回溯结构,I/O 开销倍增 --- ### 四、B+ 在 MySQL 中的实践影响 1. **索引代价** - 每建一个索引,MySQL 维护一棵独立 B+ [^2] - 写操作需更新所有相关 B+ (插入/删除成本 ↑) 2. **索引失效场景** - 未遵循最左前缀原则(如复合索引 `(a,b,c)` 查询 `WHERE b=1`) - 对索引列进行计算(如 `WHERE id+1=100`) 3. **优化建议** - 避免过度索引:单表索引建议 ≤ 5 - 优先使用自增主键:减少 B+ 节点分裂[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值