查找对应的 SSTable 文件

简介: 通过分层结构与二分查找快速定位SSTable,结合BloomFilter过滤和索引区加速查询。利用table cache与block cache缓存机制,减少磁盘IO,提升检索效率。整个过程高效有序,适用于大规模数据检索场景。(238字)

何查找对应的 SSTable 文件

在理解了这样的架构之后,我们再来看看当我们想在磁盘中查找一个元素时,具体是怎么操作的。

首先,我们会在 Level 0 层中进行查找。由于 Level 0 层的 SSTable 没有做过多路归并处理,它们的覆盖范围是有重合的。因此,我们需要检查 Level 0 层中所有符合条件的 SSTable,在其中查找对应的元素。如果 Level 0 没有查到,那么就下沉一层继续查找。

而从 Level 1 开始,每一层的 SSTable 都做过了处理,这能保证覆盖范围不重合的。因此,对于同一层中的 SSTable,我们可以使用二分查找算法快速定位唯一的一个 SSTable 文件。如果查到了,就返回对应的 SSTable 文件;如果没有查到,就继续沉入下一层,直到查到了或查询结束。

查找所有符合条件的SSTableLevel0(4个)SSTableSSTableSSTableSSTable二分查找对应的SSTable(10M)Level1SSTableSSTableSSTableSSTableSSTable二分查找对应的SSTable(100M)SSTableSSTableLevel2SSTableSSTableSSTableLevel6(1T)SSTableSSTableSSTableSSTableSSTable

可以看到,通过这样的一种架构设计,我们就将 SSTable 进行了有序的管理,使得查询操作可以快速被限定在有限的 SSTable 中,从而达到了加速检索的目的。

SSTable 文件中的检索加速

那在定位到了对应的 SSTable 文件后,接下来我们该怎么查询指定的元素呢?这个时候,前面我们学过的一些检索技术,现在就可以派上用场了。

首先,LevelDB 使用索引与数据分离的设计思想,将 SSTable 分为数据存储区和数据索引区两大部分。

DatablockDatablockDatablock数据存储区blockData过滤器数据区:支持多个过滤器,目前只有一个Bloomfilter过滤器Datablock过滤器索引区:当存在多个过滤器时,Filterblock对过滤器进行索引数据索引:对数据存储区的block进行索引,Filterblock格式:数据索引区KeyoffsetsizeMetalndexblockIndexblock记录lndexblock和Metalndexblock的位置和大小Footblock

我们在读取 SSTable 文件时,不需要将整个 SSTable 文件全部读入内存,只需要先将数据索引区中的相关数据读入内存就可以了。这样就能大幅减少磁盘 IO 次数。

然后,我们需要快速确定这个 SSTable 是否包含查询的元素。对于这种是否存在的状态查询,我们可以使用前面讲过的 BloomFilter 技术进行高效检索。也就是说,我们可以从数据索引区中读出 BloomFilter 的数据。这样,我们就可以使用 O(1) 的时间代价在 BloomFilter 中查询。如果查询结果是不存在,我们就跳过这个 SSTable 文件。而如果 BloomFilter 中查询的结果是存在,我们就继续进行精确查找。

在进行精确查找时,我们将数据索引区中的 Index Block 读出,Index Block 中的每条记录都记录了每个 Data Block 的最小分隔 key、起始位置,还有 block 的大小。由于所有的记录都是根据 Key 排好序的,因此,我们可以使用二分查找算法,在 Index Block 中找到我们想查询的 Key。

那最后一步,就是将这个 Key 对应的 Data block 从 SSTable 文件中读出来,这样我们就完成了数据的查找和读取。

利用缓存加速检索 SSTable 文件的过程

在加速检索 SSTable 文件的过程中,你会发现,每次对 SSTable 进行二分查找时,我们都需要将 Index Block 和相应的 Data Block 分别从磁盘读入内存,这样就会造成两次磁盘 I/O 操作。我们知道磁盘 I/O 操作在性能上,和内存相比是非常慢的,这也会影响数据的检索速度。那这个环节我们该如何优化呢?常见的一种解决方案就是使用缓存。LevelDB 具体是怎么做的呢?

针对这两次读磁盘操作,LevelDB 分别设计了 table cache 和 block cache 两个缓存。其中,block cache 是配置可选的,它是将最近使用的 Data Block 加载在内存中。而 table cache 则是将最近使用的 SSTable 的 Index Block 加载在内存中。这两个缓存都使用 LRU 机制进行替换管理。

那么,当我们想读取一个 SSTable 的 Index Block 时,首先要去 table cache 中查找。如果查到了,就可以避免一次磁盘操作,从而提高检索效率。同理,如果接下来要读取对应的 Data Block 数据,那么我们也先去 block cache 中查找。如果未命中,我们才会去真正读磁盘。

这样一来,我们就可以省去非常耗时的 I/O 操作,从而加速相关的检索操作了。

相关文章
|
1天前
|
存储 Serverless
哈希冲突
哈希冲突可通过优化哈希函数或采用冲突解决策略应对。开放寻址法通过线性、二次探查或双散列寻找空位,但易导致聚集,影响效率;链表法则在冲突位置构建链表,避免抢占,更适应动态数据,是常用方案之一。
|
1天前
|
NoSQL 索引
SSTable 的分层管理设计
SSTable分层管理通过将文件按层级组织,逐层合并,控制每层容量上限,减少多路归并规模,避免全量重叠,提升查询效率与系统性能,是LevelDB高效读写的核心设计。
|
1天前
|
存储 自然语言处理 分布式计算
索引构建
搜索引擎如何为万亿网页构建索引?通过分治与多路归并,将文档拆分为小集合,在内存中生成倒排索引后写入磁盘,再合并多个有序临时文件,最终生成全局倒排文件。词典可加载至内存或用B+树管理,实现高效检索。该过程类似MapReduce,支持分布式扩展。
|
1天前
|
存储 负载均衡 搜索推荐
大规模检索系统
本讲介绍大规模检索系统如何通过分布式技术加速检索。通过索引拆分,将倒排索引分散到多台服务器内存中,减少单机数据规模和磁盘访问,从而提升单次查询效率。结合分发服务器与负载均衡,实现高吞吐、低延迟的分布式检索架构。
|
1天前
|
存储 搜索推荐 索引
跳表法加速倒排索引
跳表、哈希表与位图法可加速倒排索引。跳表通过多层链表实现快速跳转,将归并查找时间降至O(log n);哈希表适用于小集合查大集合,查询可达O(1);位图则利用位运算高效求交集,适合短posting list场景,显著提升检索效率。
|
1天前
|
存储 算法 搜索推荐
数组的检索效率
二分查找通过将有序数组不断折半,每次比较中间值与目标值,缩小搜索范围至一半,实现O(log n)高效检索,显著优于遍历的O(n),适用于大规模有序数据查询。
|
1天前
|
存储 API 索引
数据结构的存储方式
数据结构底层存储只有数组和链表两种,其他如栈、队列、树、图等均为其衍生。数组支持随机访问但扩容困难,链表灵活增删但无法随机访问。所有数据结构的操作本质为“增删查改”,遍历方式分为线性迭代与非线性递归。理解二者差异,是掌握各类高级数据结构的基础。(238字)
|
1天前
|
存储 Java API
数组(顺序存储)基本原理
本章讲解数组的底层原理,区分静态与动态数组。通过静态数组实现动态数组的增删查改,揭示随机访问O(1)的成因与连续内存的利弊,助你理解数据结构本质。
|
1天前
|
自然语言处理 搜索推荐 UED
最近邻检索(上
在搜索引擎与推荐系统中,相似文章去重至关重要。本文介绍基于向量空间模型的近邻检索方法,将文档表示为TF-IDF加权的高维向量,通过计算向量间相似度识别重复内容。为提升检索效率,引入局部敏感哈希(LSH)技术,快速筛选潜在相似文章,有效优化用户体验。
|
1天前
|
存储 定位技术 索引
空间检索(下)
本文探讨“查找最近的加油站”与“查找附近的人”的本质区别,前者需动态调整查询范围以获取最近K个结果。通过GeoHash编码实现高效空间检索,提出逐步扩大查询范围的策略,并利用其一维排序特性,采用统一索引结构支持多级范围查询,在减少查询次数的同时降低存储开销,提升检索效率。