【问题标题】:How do range queries work with Sorted String Tables?范围查询如何与排序字符串表一起使用?
【发布时间】:2021-04-22 18:46:33
【问题描述】:

我有点困惑。我找不到任何关于如何对排序字符串表执行范围查询的信息。

LevelDB 和 RocksDB 支持范围迭代器,允许您在范围之间进行查询,这对于 NoSQL 来说是完美的。我不明白的是它是如何实现高效的。

表在内存(和磁盘)中排序 - 什么算法或数据结构允许在范围查询中有效地查询排序字符串表?您是否只是遍历条目并依赖缓存行充满数据?

通常我会在前面放一个前缀树,这给了我键的索引。但我猜排序字符串表会做一些不同的事情,并以某种方式利用排序。

【问题讨论】:

  • 答案可能一无所有。它只是一个以范围为条件的 for 循环。 github.com/google/leveldb/blob/master/doc/index.md#iteration
  • 如果表的长度是已知的,是否只是二分查找找到入口点,然后从那里线性扫描元素?在许多情况下,物理元素本身并没有以有序的方式存储。创建索引以提供数据的有序视图。我很抱歉,因为我不记得数据结构的名称,但它基本上是一个 B+Tree,具有所有叶节点形成一个链表的附加功能:您沿着 B+Tree 向下查找起始节点,然后然后继续遍历链接列表以获取您的范围。
  • 查看二叉树和排序良好的二叉树。

标签: algorithm data-structures okvs


【解决方案1】:

LSM 的每一层(第一层除外)都在内部按键排序,因此您可以在每一层中保留一个迭代器并使用指向字典最小元素的迭代器。层的文件在磁盘上看起来像这样:

Layer N
---------------------------------------
File1    | File2 | File3 | ... | FileN     <- filename
n:File2  |n:File3|n:File4| ... |           <- next file
a-af     | af-b  | b-f   | ... | w-z       <- key range
---------------------------------------
aaron    | alex  | brian | ... | walter    <- value omitted for brevity, but these are key:value records
abe      | amy   | emily | ... | xena
...      | ...   | ...   | ... | ...
aezz     | azir  | erza  | ... | zoidberg
---------------------------------------

First Layer (either 0 or 1)
---------------------------------------
File1    | File2 |     ...     | FileK
alex     | amy   |     ...     | andy
ben      | chad  |     ...     | dick
...      | ...   |     ...     | ...
xena     | yen   |     ...     | zane
---------------------------------------
...

假设您正在寻找 ag-d 范围内的所有内容(不包括在内)。 “范围扫描”只是找到第一个匹配元素,然后迭代图层的文件。所以你发现 File2 是第一个包含任何匹配元素的,并扫描到第一个以“ag”开头的元素。您遍历 File2,然后查看 File2 (n:File3) 的下一个文件。您检查它包含的键范围并发现它包含您感兴趣的范围中的更多元素,因此您对其进行迭代,直到您点击以“d”开头的第一个条目。你在每一层都做同样的事情,除了第一层。第一层的文件彼此之间没有排序,但它们是内部排序的,因此您可以为每个文件保留一个迭代器。您还为当前的 memtables 保留了一个(内存中的数据,仅保留在日志中)。

这永远不会变得太昂贵,因为第一层通常是在一个小的恒定阈值上压缩的。由于每一层中的文件都经过排序,并且文件内部也按 key 排序,因此您可以只推进最小的迭代器,直到所有迭代器都用完。除了初始搜索之外,每一步都必须查看固定数量的迭代器(假设是一种简单的方法),因此是 O(1)。大多数 LSM 使用块缓存,因此顺序读取通常会在大部分时间命中缓存。

最后但并非最不重要的一点是,请注意,这主要是一个概念性的解释,因为大多数实现都有一些额外的技巧来提高这些东西的效率。当您进行主要压缩时,您必须知道哪些数据包含在哪些文件范围中,即将第 N 层合并到第 N + 1 层。甚至文件级操作也可能看起来完全不同:例如,RocksDB 维护一个粗略索引在每个文件的开头带有键偏移量,以避免扫描文件中通常更大的键/值对部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多