术语 SSTable 和 LSM Tree 之间有什么区别

2024-05-14

这两个术语可以互换使用吗?

我读过有关 SSTable 工作原理的文章,通常文章都会开始提到 LSM Tree。 然而,它们似乎是同一件事。

我什么时候应该使用一个术语而不是另一个术语?


对于凡人来说,SSTables 和 LSM-Trees 的最佳解释之一可能是马丁·克莱普曼 https://stackoverflow.com/users/121436 in his 《设计数据密集型应用程序》 https://dataintensive.net书。这些数据结构在第 3 章“存储和检索”第 69 至 79 页中进行了解释。这真是一本很棒的读物,我会推荐整本书!

不耐烦的人可以在下面找到我的主题概要????


一切都从一个非常愚蠢的键值数据库开始,它仅由两个 Bash 函数实现:

db_set () {
    echo "$1,$2" >> database
}

db_get () {
   grep "^$1," database | sed -e "s/^$1,//" | tail -n 1
}

这个想法是将数据存储在类似 CSV 的文件中:

$ source database.sh

$ db_set 1 'Anakin Skywalker'
$ db_set 2 'Luke Skywalker'
$ db_set 1 'Darth Vader'

$ cat database
1,Anakin Skywalker
2,Luke Skywalker
1,Darth Vader

$ db_get 1
Darth Vader

请注意,该键的第一个值1被后续写入覆盖。

该数据库具有相当好的写入性能:db_set只是将数据附加到文件中,这通常很快。但读取效率低下,尤其是在巨大的数据集上:db_get扫描整个文件。因此,写入为 O(1),读取为 O(n)。

接下来介绍指数。索引是从数据本身派生的数据结构。维护索引总是会产生额外的成本,因此,索引总是会降低写入性能,但会提高读取性能。

最简单的索引之一是哈希索引。该索引只不过是一个字典,保存数据库中记录的字节偏移量。继续前面的示例,假设每个字符都是一个字节,则哈希索引将如下所示:

每当将数据写入数据库时​​,也会更新索引。当您想要读取给定键的值时,您可以快速查找数据库文件中的偏移量。有了偏移量,您可以使用“查找”操作直接跳转到数据位置。根据特定的索引实现,您可能会期望读取和写入的复杂度为对数。

接下来,马丁讨论存储效率。将数据附加到数据库文件会很快耗尽磁盘空间。拥有的不同键越少,这种仅附加存储引擎的效率就越低。解决这个问题的方法是压缩:

当数据库文件增长到一定大小时,您将停止向其追加内容,创建一个新文件(称为段)并将所有写入重定向到该新文件。

段是不可变的,因为它们永远不会用于附加任何新数据。修改段的唯一方法是将其内容写入新文件,中间可能进行一些转换。

因此,压缩会创建仅包含每个键的最新记录的新段。此步骤的另一种可能的增强功能是将多个片段合并为一个片段。当然,压缩和合并可以在后台完成。旧的片段就被扔掉了。

每个段(包括正在写入的段)都有自己的索引。因此,当您想要查找给定键的值时,您可以按相反的时间顺序搜索这些索引:从最新到最旧。

到目前为止,我们的数据结构具有以下优点:

✔️ 顺序写入通常比随机写入快
✔️ 使用单个编写器进程可以轻松控制并发性
✔️ 崩溃恢复很容易实现:只需顺序读取所有段,并将偏移量存储在内存索引中
✔️ 合并和压缩有助于避免数据碎片

但是,也存在一些限制:

❗ 如果段很大且数量众多,则崩溃恢复可能会非常耗时
❗ 哈希索引必须适合内存。实现磁盘上的哈希表要困难得多
❗ 范围查询(BETWEEN)几乎是不可能的


现在,有了这个背景,让我们转向 SSTable 和 LSM 树。顺便说一句,这些缩写相应地表示“排序字符串表”和“日志结构合并树”。

SSTables 与我们之前看到的“数据库”非常相似。唯一的改进是我们要求段中的记录按键排序。这似乎破坏了使用仅附加写入的能力,但这就是 LSM-Tree 的用途。我们一会儿就会看到!

与我们之前的那些简单段相比,SSTable 具有一些优势:

✔️ 由于记录已预先排序,合并段的效率更高。您所要做的就是在每次迭代中比较分段“头”并选择最低的一个。如果多个段包含相同的键,则最新段中的值获胜。这个紧凑和合并过程还保存键的排序。

✔️ 通过对键进行排序,您不再需要在索引中包含每个键。如果钥匙B已知位于键之间的某个位置A and C你可以做一个扫描。这也意味着范围查询是可能的!

最后一个问题是:如何获得按键排序的数据?

帕特里克·奥尼尔等人描述了这个想法。在他们的“日志结构合并树(LSM-Tree)” https://www.cs.umb.edu/%7Eponeil/lsmtree.pdf很简单:内存中有一些数据结构,例如红黑树或AVL树,它们擅长对数据进行排序。因此,您将写入分为两个阶段。首先,将数据写入内存中的平衡树。其次,将树刷新到磁盘上。实际上,可能有两个以上的阶段,较深的阶段比上层更大且“慢”(如在另一个答案中显示 https://stackoverflow.com/a/58169581/750510).

  1. 当写入到来时,您将其添加到内存中的平衡树中,称为 memtable。
  2. 当memtable变大时,它会被刷新到磁盘。它已经排序了,所以它自然会创建一个 SSTable 段。
  3. 同时,写入由新的内存表处理。
  4. 读取首先在内存表中查找,然后在段中查找,从最近的到最旧的。
  5. 如前所述,片段会在后台不时被压缩和合并。

该方案并不完美,它可能会突然崩溃:内存表作为内存中的数据结构会丢失。这个问题可以通过维护另一个仅附加文件来解决,该文件基本上复制了内存表的内容。数据库只需要在崩溃后读取它即可重新创建内存表。

就是这样!请注意,上面描述的简单仅附加存储的所有问题现在都已解决:

✔️ 现在在崩溃的情况下只有一个文件可供读取:memtable 备份
✔️ 索引可能很稀疏,因此更容易安装 RAM
✔️ 现在可以进行范围查询


TLDR:SSTable 是一种键排序的仅附加键值存储。 LSM 树是一种基于平衡树的分层数据结构,它允许 SSTable 存在,而不会同时存在排序和仅附加的争议。


恭喜,您已经读完了这篇长文!如果您喜欢这个解释,请确保不仅支持这篇文章,还支持一些马丁的答案在这里 https://stackoverflow.com/users/121436/martin-kleppmann?tab=answers以及。请记住:所有功劳都归他所有!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

术语 SSTable 和 LSM Tree 之间有什么区别 的相关文章

  • 删除大量记录需要很长时间

    我有一个包含约 60 000 行的数据库表 在 SQL Server 2012 Express 上运行 我使用以下代码来清除旧行 Deleting CPU measurements older than oldestAllowedTime
  • 非规范化如何提高数据库性能?

    我听说过很多关于非规范化的内容 它是为了提高某些应用程序的性能而进行的 但我从来没有尝试过做任何相关的事情 所以 我只是好奇 规范化数据库中的哪些地方会使性能变差 或者换句话说 非规范化原则是什么 如果我需要提高性能 如何使用此技术 非规范
  • 从数据库 MYSQL 和 Codeigniter 获取信息

    如果你们需要其他信息 上一个问题就在这里 从数据库中获取信息 https stackoverflow com questions 13336744 fetching information from the database 另一个更新 尽
  • 如何在asp.net中按下按钮后刷新Gridview

    我正在尝试制作一个简单的图书馆数据库 我在网格视图中列出搜索结果 然后有一个文本框和一个按钮 用户输入 isbn 并单击贷款按钮 然后 如果有足够数量的物品 itemNumber gt 0 则由用户借出 这是用户界面的屏幕截图 我的问题是
  • DBMS 中的阻塞因素

    DBMS 中的阻塞因素是什么 我查看的位表示它是每个记录的块的下限值 因此 B R 下限 其中 B 是块大小 R 是记录 我只是想知道 有人可以告诉我它使用的主要原因 以及它是否真的是地板 我对 FLOORED 的理解是 1 5 降到 1
  • 内存高效的大型数据集流式传输到 S3

    我正在尝试使用 SQL alchemy 复制 S3 大型数据集 大于 RAM 我的限制是 我需要使用 sqlalchemy 我需要将内存压力保持在最低水平 我不想使用本地 filsystem 作为中间步骤将数据发送到 s3 我只想通过管道将
  • Android 预填充数据库 [重复]

    这个问题在这里已经有答案了 我正在开发一个 Android 应用程序 需要在该应用程序的数据库中填充多个条目 一个表 包含 1000 10000 行 然后用户才能使用该应用程序 我浏览了一些教程 但不确定执行此操作的最佳方法 我是否应该在每
  • MySQL:为什么 IN 子句中的第 5 个 ID 会极大地改变查询计划?

    给出以下两个查询 Query 1 SELECT log id FROM log WHERE user id IN 188858 188886 189854 203623 204072 and type in 14 15 17 ORDER B
  • Django 模型同步表

    如果我更改 Django 模型中的字段 如何将其与数据库表同步 我是否需要在数据库上手动执行此操作 或者是否有工具可以帮助完成此过程 唉 Django 不支持任何简单的解决方案 django 唯一能为你做的就是使用与新模型匹配的新表重新启动
  • 如何使用索引更改表的列?

    我想将带有某些索引的表中 a 列的列大小从 varchar 200 更改为 varchar 8000 我应该如何进行 既然是VARCHAR你正在增加尺寸 然后简单地ALTER TABLE ALTER COLUMN https learn m
  • 将“选票”存储在数据库中

    我正在编写一个 Intranet 应用程序 其功能之一大致类似于内容投票 与 SO Amazon 和许多其他网站的做法不同 假设每个可投票的内容都有一个唯一的 ID 并且每个用户 他们经过身份验证 都有一个唯一的 ID 最简单的方法似乎是有
  • 分区表查询仍然扫描所有分区

    我有一个包含超过十亿条记录的表 为了提高性能 我将其分区为30个分区 最常见的查询有 id 在他们的 where 子句中 所以我决定对表进行分区id column 基本上 分区是这样创建的 CREATE TABLE foo 0 CHECK
  • PostgreSQL 中的仅索引扫描和位图索引扫描有什么区别?

    在我的查询中 我只想调用具有精确 where 条件的数据 这些where条件是在index html中创建的 Bu 解释显示了位索引扫描 我不明白为什么 我的查询如下所示 Select r spend r date from metadat
  • 如何在 PHP 中实现前向索引?

    我希望在 PHP 中实现一个简单的前向索引器 是的 我确实知道 PHP 并不是完成这项任务的最佳工具 但无论如何我还是想这样做 其背后的理由很简单 我想要一个 并且是 PHP 版本 让我们做一些基本假设 整个互联网包括 大约五千个 HTML
  • SQLite 数据库安全

    我正在构建一个使用 Sqlite DB 的应用程序 用户可以将他们的信息输入数据库并检索它们 但是 我希望他们能够备份 sqlite 数据库 我所做的是将 sqlite 数据库放入文档文件夹中 以便他们可以使用 iTunes 将其检索出来
  • .NET 表适配器:获取与填充?

    在处理数据库中的数据 强类型或其他方式 时 我似乎总是使用 Get 并且我从未真正需要使用 Fill 尽管在提取和更新数据时我可以轻松地使用 Fill 而不是 get 任何人都可以提供有关每种方法的含义和陷阱的指导吗 在什么情况下最好使用其
  • 如何检测数据库类型?

    我需要确保我连接的数据库是 MySQL 而不是 PostgreSQL 或 Microsoft SQL Server 我怎样才能知道正在使用哪种类型的数据库 第一个提示可能是如果您尝试使用 mySQL 数据库驱动程序连接到 PostgreSQ
  • 在json文件中导出neo4j数据库

    我想以 JSON 文件导出 Neo4j 图形数据库 This is a Export JSON button in Neo4j web UI version as shown in attached image below 但是 Neo4j
  • 如何仅选择数组中的第一列并对其求和?

    这是我的代码 import numpy as np contrainte1 1080 0 65 minutes tous les jours contrainte2 720 0 55 minutes du lundi au vendredi
  • 表中主键的最佳实践是什么? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在设计表时 我养成了一种习惯 即有一列是唯一的 并且我将其作为主键 根据要求 可以通过三种方式实现 自动递增的标识整数列 唯一标识符 GUID

随机推荐

  • 为什么字符串和对象的别名是小写的?

    以下是 C 中的别名列表 赞美C 中的 String 和 string 有什么区别 https stackoverflow com questions 7074 whats the difference between string and
  • 如何以编程方式将 SMTP 服务器详细信息存储(保存)回 web.config

    搜索 StackOverflow 我发现这个问题是关于如何从 Web Config 检索 SMTP 设置 https stackoverflow com questions 2019175 how to programmatically r
  • StreamReader 消耗的字节数

    有没有办法知道 StreamReader 使用了流的多少字节 我有一个项目 我们需要读取一个文件 该文件具有文本标题 后跟二进制数据的开头 我最初尝试读取该文件是这样的 private int dataOffset void ReadHea
  • grid.arrange 中的错误 -rangeGrob() 函数

    我有两个图 p1 和 p2 我试图使用 grid arrage 绘制它们 我的代码如下所示 grid arrange p1 p2 ncol 2 top textGrob Distribution across each day of the
  • 如何干净地处理全局变量?

    我有许多 aspx 页面 50 我需要在每个页面中声明一些 5 7 全局变量 一个页面中的变量独立于其他页面 即使有些变量可能相同 目前我在页面顶部和任何函数之外声明 我应该采取不同的方法吗 这种方法有副作用吗 如果完全重复 请告诉我 谢谢
  • Material UI 组件中的媒体查询

    我在 React js 项目中使用 Material UI 组件 出于某种原因 我需要对某些组件进行自定义 以使其根据屏幕宽度进行响应 我已经添加了media query并将其作为组件中的样式属性传递 但不起作用 知道吗 我正在使用这样的代
  • 给定一组类,调用具有匹配方法参数的类

    我有两个或多个从单亲继承的类 他们都已经超载了handle方法 但每个类的句柄方法都有不同的参数 class CommandHandler class FooCommandHandler public CommandHandler publ
  • 无法让 Cordova 文本转语音插件工作

    我正在尝试各种 TTS 插件 包括位于https github com vilic cordova plugin tts https github com vilic cordova plugin tts 但无法让任何工作 例如 根据文档
  • 有人可以解释以下异或属性

    我的一个论坛提到给定的数组n数字 arr 0 n 1 以下条件成立 is the xor运算符 f l r f 0 r f 0 l 1 where f l r arr l arr l 1 arr r 我检查了上面的数组数量和不同的值l an
  • 如何封装.NET无状态状态机

    我有一个项目 其中大部分是线性工作流程 我正在尝试使用 NET Statelesslibrary https github com dotnet state machine stateless充当工作流引擎 状态机 示例的数量有限 但我整理
  • 如何在我的 html 中使用 Flaticon 中的图标?

    我想给我的网站一些图标 现在我看到很多人使用Flaticon这个网站 我所做的就是在 CSS 中添加这样的内容 Font 1 font face font family Flaticon1 src url flaticon1 eot src
  • 以下两个 lambda 函数的空间复杂度

    我正在阅读以下内容 https en wikibooks org wiki Haskell Graph reduction https en wikibooks org wiki Haskell Graph reduction 其内容如下
  • 我如何移动粘性/捕捉 wpf 窗口

    当我移动 主 窗口时 我想移动两个或更多粘性窗口 我想做这样的事情 private void MainWindow PreviewMouseMove object sender MouseEventArgs e if e LeftButto
  • 将 Python 输入字符串限制为特定字符和长度

    我刚刚开始学习我的第一种真正的编程语言 Python 我想知道如何限制用户输入raw input特定字符和特定长度 例如 如果用户输入包含除字母之外的任何内容的字符串 我想显示一条错误消息a z 我想显示超过 15 个字符的用户输入之一 第
  • 在 WordPress 中使用自定义字段进行搜索

    我正忙于使用 WordPress 开发 Web 应用程序 我创建了一个带有一些自定义字段的自定义帖子 当我使用 WordPress 搜索框搜索帖子时 仅返回标题与搜索字符串匹配的帖子 我想在搜索域中添加自定义字段 我可以在 WordPres
  • 预乘 Alpha 合成

    我正在尝试实现预乘阿尔法混合 在本页 什么是颜色混合 https learn microsoft com en us previous versions windows xna bb976070 v xnagamestudio 41 它们确
  • 在读取正文之前拒绝 HTTP 请求

    我正在开发一个网站 用户需要上传一些非常大的文件 该网站是用 PHP 编写的 在某些情况下 我想根据标头拒绝文件 理想情况下 我想在收到标头后立即拒绝请求 而不读取正文 如果标头足以表明该文件应被拒绝 则没有理由读取 200M 的文件 此外
  • POSIX SH 构建循环变量,其元素包含空格

    这是我需要的代码 bin sh x1 a1 a2 x2 b1 b2 list SOMETHING for x in list do echo x done 以及我想要的输出 a1 a2 b1 b2 问题是 应该做什么SOMETHING是 我
  • PSQL [错误] - 值被识别为列

    前几天刚开始学习数据库 我遇到了这个问题 我的值被识别为一列 并且它吐出了一个错误 这是我的News table id bodyText url createdAt updatedAt 这是我在 psql 中运行的命令 INSERT INT
  • 术语 SSTable 和 LSM Tree 之间有什么区别

    这两个术语可以互换使用吗 我读过有关 SSTable 工作原理的文章 通常文章都会开始提到 LSM Tree 然而 它们似乎是同一件事 我什么时候应该使用一个术语而不是另一个术语 对于凡人来说 SSTables 和 LSM Trees 的最