【问题标题】:Persistence Strategies for main-memory B+ Trees主存 B+ 树的持久性策略
【发布时间】:2011-07-22 13:37:12
【问题描述】:

我正在尝试使用 C++ 为键值对开发主内存索引。我需要确保索引在崩溃后是可恢复的。我正在使用我发现的 CSB+-Tree 实现(BSD 许可证)here 我面临的主要挑战是在重新实例化节点后维护父子关系数据。 我已经搜索了各种策略来将“树结构”保存到磁盘或从磁盘恢复。其中一些是:

  1. 以 Pre-order 保存节点对象并为空子指针写入 NULLS。
  2. 为节点提供 IDS 并在写入时保存节点的 ID 而不是指针 到磁盘,然后在使用 ID 重新实例化期间解析指针。
  3. 保存时使用文件偏移值(物理内存中的地址)而不是子节点的主内存地址。这可能意味着我必须从叶子向上保存。

我还查看了几个序列化库。 Google ProtocolBuffers 和 Boost 序列化。

现在实现中的“节点”有许多指针变量。其中一些是指向其他节点的指针,而另一些是指向“键值”的指针。下面的代码是简化版,保留了本质。

struct NodeHead  
{  
    NodeHead *null; // null indicates internal node  
    char *children; // ptr to children  
    NodeEntry entries[1]; // entry array  
}

struct NodeEntry  
{  
    uint16_t offset;   // offset to NodeHead of the key in byte  
    uint8_t next;   // index of the next entry; 0xff means null  
    uint8_t num;    // [0]: number of entries in use  
};

我正在考虑将条目值直接写入节点头的数据中,而不是保存链接。并为每个 NodeHead 实例提供一个 ID 并使用它来维护“子”关系。如果能以更好的方式做到这一点,我想要一些建议。

【问题讨论】:

  • 如果崩溃时您说的是流产或任何硬中断,您将无法序列化任何内容...那么您的策略是什么让数据持久之前 i> 你崩溃了?在每次修改时对所有内容进行序列化不太可能。
  • 我不会在每次修改时进行序列化。我将有定期检查站。在检查点期间,我更愿意将索引的“快照”(连同叶子中的数据)保存到磁盘上。这样启动后我可以恢复索引结构。在 2 个检查点之间,我将保留所有事务的日志,以便在恢复到最新提交的操作后更新索引快照。关于将快照保存到磁盘,我发现了一个类似的问题问stackoverflow.com/questions/872070/…。我被困在如何继续
  • 您也可以执行选项 3,让索引本身引用(没有指针仅引用页面偏移量 - 在页面中分配索引),然后当您对索引进行快照时,您可以检查索引 @ 987654324@ 并检查该索引页是否已更新,然后将整个脏索引页复制到磁盘。无需遍历树,只需索引页的索引。 [我提出了类似于 CUDA 内存复制问题的建议——我一定是个小马驹 :) ]

标签: c++ database data-structures indexing


【解决方案1】:

数据(键、值)对是单独保存在磁盘上,还是需要将它们与索引一起保存?当数据在磁盘上时,您是将数据本身保存在内存中,还是仅驻留在索引内存中?如果整个数据集驻留在内存中,则根本不要保留树结构。只需保存(键,值)对的有序列表并在加载时重建树。我从未使用过那个库,但任何合理的 B-tree 实现都应该能够非常有效地从预先排序的记录流中构建内存中的 B-tree。

【讨论】:

    猜你喜欢
    • 2012-02-02
    • 1970-01-01
    • 2018-07-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    • 2010-12-18
    相关资源
    最近更新 更多