【问题标题】:How to implement an "index join" data structure in JavaScript?如何在 JavaScript 中实现“索引连接”数据结构?
【发布时间】:2022-01-23 07:38:15
【问题描述】:

我正在学习有关关系数据查询处理的 join algorithms。最简单的情况是嵌套循环连接:

function nestedJoin(R, S, compare) {
  const out = []
  
  for (const r of R) {
    for (const s of S) {
      if (compare(r, s)) {
        out.push([ r, s ])
      }
    }
  }

  return out
}

compare 将比较 join 属性。

我想知道的情况是索引连接。从该备忘单复制到 JS 中,我们有:

function indexJoin(R, S) {
  const out = []
  
  for (const r of R) {
    const X = findInIndex(S.C, r.c)
    for (const s of X) {
      out.push([ r, s ])
    }
  }

  return out
}

但是findInIndex(S.C, r.c) 是什么?传递给它的是什么 (S.C)?它是如何工作的?

join indices paper 是这样说的:

没有索引,两种基于排序 [4] 和散列的基本算法 [5, lo] 避免嵌套循环方法的高昂成本。

连接索引是一种二元关系。它只包含成对的代理,这使得 (它很小。但是,为了一般性,我们假设它并不总是适合 RAM。 因此,连接索引必须是聚集的。因为我们可能需要快速访问 JI 元组通过 r 值或 s 值取决于是否有选择 关系 R 或 S,一个 JI 应该聚集在 (r, s) 上。一个简单而统一的解决方案 是维护JI的两个副本,一个集群在r上,另一个集群在 s。每个副本都由 W-tree 实现,这是通用的有效变体 B-树 [l, 71.

那么如果它是一个 B+tree,那么每个 B+tree 中会使用什么键和值,以及如何使用键和值(插入键和获取值的顺序是什么)?另外,如果“连接索引”是在 JavaScript 中,就不能像这样实现吗?

const joinIndex = {}

function join(r, s) {
  const rest = joinIndex[r.c] = joinIndex[r.c] ?? {}
  rest[s.c] = true
}

function findInIndex(leftKey) {
  return Object.keys(joinIndex[leftKey])
}

请说明如何使用我的方法或 B+tree 方法来实现连接算法。如果是 B+tree 方法,则不需要实现 B+tree,只需说明如何将事物插入/取出 2 个 B+tree,以便更清楚地解释算法。

【问题讨论】:

    标签: javascript database indexing data-structures b-tree


    【解决方案1】:

    首先,论文所说的连接索引,最好可以想象成一个表,实现了两个表之间的多对多关系。此连接索引表中的一条记录由两个外键组成:一个引用 R 表中的主键,另一个引用 S 表中的主键。

    我没有得到备忘单中使用的S.C 符号。但很明显,您需要以某种方式指定要使用的 which 连接索引,更具体地说,您要在其上使用哪个 B+Tree(集群)(如果定义了其中两个) ,最后,你想在其中找到哪个值(r.c,r 的键)。

    B+tree 的作用是提供一个有序的哈希表,即你可以在其中有效地搜索一个键,并且可以轻松地从该点按顺序遍历后续条目。在 join index 的这种特殊用途中,这允许您有效地找到给定 r1 的所有对 (r1, s)。其中第一个可以通过从 B+树的根向下钻到具有 r1 的第一个叶子来找到。然后向前遍历 B+tree 的底层会找到所有其他具有 r1 的元组,直到遇到不再具有此 r1 值的元组.

    请注意,您仍然需要原始表的索引,以便找到给定键的完整记录。实际上,这也可以使用 B+Tree 来完成,但在 JavaScript 中,一个简单的字典(普通对象)就足够了。

    所以在 JavaScript 语法中我们可以想象这样的事情:

    // Arguments:
    //  - joinIndexTree: a B+Tree having (rKey, sKey) tuples, keyed and ordered by rKey.
    //  - rKey: the key to search all matches for
    function findInIndex(joinIndexTree, rKey) {
      let result = []; // This will collect all the sKey for
                       // which thee is a (rKey, sKey)
      // Find left-most location in B+Tree where rKey should occur (if present)
      let btreeCursor = joinIndexTree.find(rKey);
      if (btreeCursor.EOF()) return result; // At the far-right end of the B+Tree
      let tuple = btreeCursor.get();  // Read the tuple found at this location
      while (tuple[0] == rKey) { // First member of tuple matches rKey
         result.push(tuple[1]); // Collect the corresponding s-value
         btreeCursor.next(); // Walk to the next tuple
         if (btreeCursor.EOF()) break; // At the end of the B+Tree
         tuple = btreeCursor.get();  // Read the tuple found at this location
      }
      return result;
    }
    

    主程序是:

    const joinIndexTree = ;// B+Tree with (rKey, sKey) pairs, ordered by rKey
    const sIndex = Object.fromEntries(S.map(s => [s.id, s])); // dictionary
    
    function indexJoin(joinIndexTree, R, S, sIndex) {
      const out = []
      
      for (const r of R) {
        const sids = findInIndex(joinIndexTree, r.id)
        for (const s_id of sids) {
          const s = sIndex[s_id]; // Look up by primary key index
          out.push([ r, s ])
        }
      }
    
      return out
    }
    

    当您只需要对表(查询)进行只读操作时,您可以创建一个数组字典,而不是 B+Tree,在其中您可以通过joinIndex[r.id] 查找并获得s.id 的数组价值观。这当然很容易设置和使用,但是当表不是只读的时,保持更新会很痛苦。

    作为 B+Tree 的替代方案,您还可以使用其他平衡搜索树,例如 AVL 和红黑树,但根据我的经验,B+Trees 具有更优越的性能。

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 2020-05-20
      • 2013-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多