【博客719】时序数据库基石:LSM Tree的增删查改

news2025/2/8 14:22:31

时序数据库基石:LSM Tree的增删查改

LSM结构

LSM树将任何的对数据操作都转化为对内存中的Memtable的一次插入。Memtable可以使用任意内存数据结构,如HashTable,B+Tree,SkipList等。对于有事务控制需要的存储系统,需要在将数据写入Memtable之前,先将数据写入持久化存储的WAL(Write Ahead Log)日志。由于WAL日志是顺序Append到持久化存储的,因此无论对磁盘还是SSD都是非常友好的。
在这里插入图片描述

LSM树各类操作

前面我们提到了LSM的结构和合并,现在来看下LSM结构的增删查改:

再强调一次下面的概念:

  • LSM树的增加、删除、修改(这三个都属于写操作)都是在内存中倒腾,完全没涉及到磁盘操作。当要修改现有数据时,LSM Tree并不直接修改旧数据,而是直接将新数据写入新的SSTable中。同样的,删除数据时,LSM Tree也不直接删除旧数据,而是写一个相应数据的删除标记的记录到一个新的SSTable中
  • LSM Tree写数据时对磁盘的操作都是顺序块写入操作,而没有随机写操作。
  • LSM Tree这种独特的写入方式,导致在查找数据时,LSM Tree就不能像B+树那样在一个统一的索引表中进行查找,而是从最新的SSTable到老的SSTable依次进行查找。如果在新SSTable中找到了需查找的数据或相应的删除标记,则直接返回查找结果;如果没有找到,再到老的SSTable中进行查找,直到最老的SSTable查找完
  • 为了提高查找效率,LSM Tree对SSTable进行分层、有序组织,也就是说把SSTable组织成多层,同一层可以有多个SSTable,同一个数据在同一层的多个SSTable中可以不重复,而且数据可以做到在同一层中是有序的,即每一个SSTable内的数据是有序的,前一个SSTable的最大数据值小于后一个SSTable的最小数据值(实际情况比这个复杂,后面会介绍)。这样可以加快在同一层SSTable中的数据查询速度。同时,LSM Tree会将多个SSTable合并(Compact)为一个新的SSTable,这样可以减少SSTable的数量,同时把修改前的数据或删除的数据真正从SSTable中删除,减小了SSTable的大小(这就是Log-Structured Merge Tree名字中Merge一词的由来),对提高查找性能极其重要
  • LSM树将任何的对数据操作都转化为对内存中的Memtable的一次插入
  • Memtable可以使用任意内存数据结构,如HashTable,B+Tree,SkipList
  • 对于有事务控制需要的存储系统,需要在将数据写入Memtable之前,先将数据写入持久化存储的WAL(Write Ahead Log)日志。由于WAL日志是顺序Append到持久化存储的,因此无论对磁盘还是SSD都是非常友好的。

小话题:加入了WAL的结构如下在这里插入图片描述

LSM树支持常见的变更操作,插入,删除,更新。常见的实现里,为了统一变更的数据结构标识,往MemTable里写入的除了<Key, TimeStamp, Value>三元组外,还会带上操作的类型。所有的变更操作并不直接修改磁盘上的数据,而只是将变更写入MemTable。因此数据变更除了WAL日志一次顺序IO之外,没有额外的任何随机IO,插入效率非常高。

1、数据写入

无WAL的写入:

由于 LSM tree 只会进行顺序写入,所以自然而然地就会引出这样一个问题,写入的数据可能是任意顺序的,我们又如何保证数据能够保持 SSTable 要求的有序组织呢?
这就需要引入新的常驻内存 (in-memory) 数据结构: memtable_了, _memtable 的底层数据结构可以是类似红黑树这种,当有新的写入操作则将数据插入到红黑树中。

写入操作会先把数据存储到红黑树中,直至红黑树的大小达到了预先定义的大小。一旦红黑树的大小达到阈值,就会把数据整个刷到磁盘中,这个过程就可以把数据保证有序写入了。经过一层数据结构的承接,就可以保证单向顺序写入的同时,也能保证数据的有序。

在这里插入图片描述

注意:如果是有WAL的写入,则是以下操作

  • 当收到一个写请求时,会先把该条数据记录在WAL Log里面,用作故障恢复。

  • 当写完WAL Log后,会把该条数据写入内存的SSTable里面(删除是墓碑标记,更新是新记录一条的数据),也称Memtable。注意为了维持有序性在内存里面可以采用红黑树或者跳跃表相关的数据结构。

  • 当Memtable超过一定的大小后,会在内存里面冻结,变成不可变的Memtable,同时为了不阻塞写操作需要新生成一个Memtable继续提供服务。

  • 把内存里面不可变的Memtable给dump到到硬盘上的SSTable层中,此步骤也称为Minor Compaction,这里需要注意在L0层的SSTable是没有进行合并的,所以这里的key range在多个SSTable中可能会出现重叠,在层数大于0层之后的SSTable,不存在重叠key。

  • 当每层的磁盘上的SSTable的体积超过一定的大小或者个数,也会周期的进行合并。此步骤也称为Major Compaction,这个阶段会真正 的清除掉被标记删除掉的数据以及多版本数据的合并,避免浪费空间,注意由于SSTable都是有序的,我们可以直接采用merge sort进行高效合并。

2、数据变更

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、数据删除

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、数据查找

  • 根据LSM Tree的写入特点我们知道,如果一项数据更新多次,这项数据可能会存储在多个不同的SSTable中,甚至一项数据的不同部分的最新数据内容存储在不同的SSTable中(数据部分更新的场景)。LSM Tree把这种现象叫做空间放大(space amplification),因为一项数据在磁盘中存储了多份副本,而老的副本是已经过时了的,不需要的,数据实际占用的存储空间比有效数据需要的大。

  • 空间放大这种现象导致LSM Tree的查找过程是这样的:按新到老的顺序查找SSTable,直到在某个(或某些个)SSTable中查找到了所需的数据,或者最老的SSTable查找完也没有找到需要的数据。具体查找顺序为:先在内存MemTable中查找,然后在内存中的Immutable MemTable中查找,然后在level 0 SSTable中查找,最后在level N SSTable中查找。

  • 查找某个具体的SSTable时,一般先把SSTable的元数据block读到内存中,根据BloomFilter可以快速确定数据在当前SSTable中是否存在,如果存在,则采用二分法确定数据在哪个数据block,然后将相应数据block读到内存中进行精确查找。

  • 从LSM Tree数据查找过程我们可以看到,为了查找到目标数据,我们需要读取并查找不包含目标数据的SSTable,如果目标数据在最底层level N的SSTable中,我们需要读取和查找所有的SSTable!LSM Tree把这种读取和查找了无关SSTable的现象叫做读放大(read amplification)。

点查:

范围查询

范围查询根据表的查询Key的范围区间[StartKey, EndKey],通常会先对StartKey在LSM树上逐层做LowerBound查询,即每一层上找到大于或等于StartKey的数据的起始位置。由于LSM树每一层都是有序的(内存中的MemTable如果是无序的Hash表则需要全部遍历),只需要从这个起始位置开始读取数据,直到读取到EndKey为止。

5、数据合并

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1850731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库设计文档编写

PS&#xff1a;建议使用第三种方法 方法1&#xff1a;使用 Navicat 生成数据库设计文档 效果 先看简单的效果图&#xff0c;如果效果合适&#xff0c;大家在进行测试使用&#xff0c;不合适直接撤退&#xff0c;也不浪费时间。 随后在docx文档中生成目标字段的表格&#xf…

dex文件结构(二):dex文件加载基本原理

return mClassLoader; } 1.3 ApplicationLoaders.getClassLoader public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent){ //Class.getSystemClassLoader返回的是一个PathClassLoader //baseParent是BootClassLoader ClassLoader basePare…

【仿真建模-anylogic】Network代码解析

Author&#xff1a;赵志乾 Date&#xff1a;2024-06-22 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 类图 2. 代码解析 //************************核心字段************************* // Network所属的level private transient Leve…

windows10远程桌面端口,Windows 10远程桌面端口修改的两个方法

在Windows 10系统中&#xff0c;远程桌面功能允许用户通过网络从一台计算机远程访问和控制另一台计算机。默认情况下&#xff0c;远程桌面服务使用的端口是3389。然而&#xff0c;出于安全考虑&#xff0c;许多管理员和用户希望修改这一默认端口。本指南将详细介绍如何在Window…

乌班图Ubuntu 24.04 SSH Server 修改默认端口重启无效

试用最新的乌班图版本&#xff0c;常规修改ssh端口&#xff0c;修改完毕后重启sshd提示没有找到service&#xff0c;然后尝试去掉d重启ssh后查看状态&#xff0c;端口仍然是默认的22&#xff0c;各种尝试都试了不行&#xff0c;重启服务器后倒是端口修改成功了&#xff0c;心想…

AcWing算法基础课笔记——高斯消元

高斯消元 用来求解方程组 a 11 x 1 a 12 x 2 ⋯ a 1 n x n b 1 a 21 x 1 a 22 x 2 ⋯ a 2 n x n b 2 … a n 1 x 1 a n 2 x 2 ⋯ a n n x n b n a_{11} x_1 a_{12} x_2 \dots a_{1n} x_n b_1\\ a_{21} x_1 a_{22} x_2 \dots a_{2n} x_n b_2\\ \dots \\ a…

陈好与王星越中戏传承

陈好与王星越&#xff1a;中戏传承&#xff0c;万人迷与未来之星在娱乐圈的星光璀璨中&#xff0c;我们时常被那些耀眼的明星所吸引&#xff0c;但你是否曾想过&#xff0c;他们背后的成长之路&#xff0c;是如何被一位位优秀的老师所指引的呢&#xff1f;今天&#xff0c;就让…

刷代码随想录有感(113):动态规划——爬楼梯plus

题干&#xff1a; 代码&#xff1a; #include<bits/stdc.h> using namespace std;int main(){int n,m;cin>>n>>m;vector<int>dp(n 1, 0);dp[0] 1;for(int j 0; j < n; j){for(int i 1; i < m; i){if(j > i)dp[j] dp[j - i];}}cout<&…

交互式知识库问答:一种结合大型语言模型的多轮交互方法

在当今信息爆炸的时代&#xff0c;人们每天都要处理海量的数据和信息。在这样的背景下&#xff0c;基于知识库的问答系统&#xff08;KBQA&#xff09;成为了一个重要的研究领域&#xff0c;它旨在使计算机能够理解自然语言提出的问题&#xff0c;并从结构化的知识库中检索出准…

以太坊==给合约转入/查询合约剩余/合约转给某账户/结构体/MAP

转入 必须要定义该函数&#xff0c;或者定义fallback // 接收以太币 receive() external payable {} // Corrected Line // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;contract SimpleStorage {uint256 private storedData;// 事件&#xff0c;用于通知数据变更e…

【Redis】黑马点评短信登录

https://blog.csdn.net/qq_33888850/article/details/129770077 https://blog.csdn.net/weixin_51515308/article/details/128010464 https://www.bilibili.com/video/BV1cr4y1671t?p24 导入数据库 https://github.com/MagicToDo/hm-dianping sql文件在 hm-dianping-init\src…

35.简易远程数据框架的实现

上一个内容&#xff1a;34.构建核心注入代码 34.构建核心注入代码它的调用LoadLibrary函数的代码写到游戏进程中之后无法调用&#xff0c;动态链接库的路径是一个内存地址&#xff0c;写到游戏进程中只把内存地址写过去了&#xff0c;内存地址里的内容没写过去&#xff0c;导致…

【Git】 -- Part2 -- 分支管理

1. 分支 在 Git 中&#xff0c;分支&#xff08;Branch&#xff09;是用于在项目中创建独立开发线路的机制。分支使得开发者可以在不影响主干&#xff08;main 或 master&#xff09;的情况下进行实验、开发新功能或修复 Bug。 举个例子&#xff1a; 分⽀就好像是科幻电影⾥⾯…

软件开发教学:在线教育系统源码解析及教育培训小程序搭建实战

本篇文章&#xff0c;笔者将以“从零开始的软件开发教学”为主题&#xff0c;详细解析在线教育系统的源码&#xff0c;并通过实际操作来搭建一个教育培训小程序。 一、在线教育系统概述 在线教育系统是一个综合性的网络平台&#xff0c;旨在通过互联网提供教育资源和服务。该系…

http和https的区别在哪

HTTP&#xff08;超文本传输协议&#xff09;和HTTPS&#xff08;超文本传输安全协议&#xff09;之间存在几个关键区别主要涉及安全性、端口、成本、加密方式、搜索引擎优化&#xff08;SEO&#xff09;、身份验证等方面 1、安全性&#xff1a;HTTP&#xff08;超文本传输协议…

Day5(和为s的两个数字)双指针

输入一个递增排序的数组和一个数字s&#xff0c;在数组中查找两个数&#xff0c;使得它们的和正好是s。如果有多对数字的和等于s&#xff0c;则输出任意一对即可。 二、思路 1.首先&#xff0c;将不符合要求的值给排除&#xff0c;有以下三种&#xff1a; 数组元素个数不足两个…

ArrayList知识点(面试)

上一篇我们说了hashmap的相关知识点&#xff0c;这一篇我们再说一些ArrayList的相关知识&#xff0c;因为ArrayList也是我们项目中比较常用的。 ArrayList(底层是数组) 底层工作原理 首先&#xff0c;在构造ArrayList的时候会先看有没有指定容量&#xff0c;如果没有&#xf…

Flutter【组件】可折叠文本组件

简介 flutter 可折叠文本组件。 点击展开&#xff0c;收起折叠文本。支持样式自定义 github地址&#xff1a; github.com/ThinkerJack… pub地址&#xff1a;https://pub.dev/packages/jac_uikit 展开收起文本 使用方式&#xff1a; ExpandableText(content: 测试 * 50,ma…

一文搞懂Linux信号【下】

目录 &#x1f6a9;引言 &#x1f6a9;阻塞信号 &#x1f6a9;信号保存 &#x1f6a9;信号捕捉 &#x1f6a9;操作信号集 1.信号集操作函数 2.其它操作函数 &#x1f6a9;总结&#xff1a; &#x1f6a9;引言 在观看本博客之前&#xff0c;建议大家先看一文搞懂Linux信…

JR-8000系列机架式多路4K超高清光端机

集中式 4K超高清光传输设备 1 产品特性 ⚫ 支持高达 8 通道 SMPTE 全格式 SDI 信号输入 ⚫ 发送端带有 LOOPOUT 环出端口&#xff0c;具备消抖动功能&#xff0c;可作为信号调理或级联信号源使用 ⚫ 接收端支持双输出端口 ⚫ 支持传输速率&#xff1a;143Mbps-11.88Gbps ⚫…