【问题标题】:Storing dynamic objects with growing lists on disk在磁盘上存储具有不断增长的列表的动态对象
【发布时间】:2012-01-14 13:40:36
【问题描述】:

好的,到目前为止,我一直在主内存中开发一个系统,该系统具有许多不同的对象,每个对象都存储系统中其他对象的列表。现在我想将其移至持久存储。我不是在寻找使用 DBMS 的明显答案,因为重点是我正在为我的系统编写自定义数据库。

现在我为每个对象分配一个 ID。可以在表中查找 id,以找到该对象的数据位置的块和偏移量。现在每个对象都有指向系统中其他对象的列表/集合。所以很明显,在存储中,它们将是 8 字节的列表(使用 long 作为 id)id,可用于查找其他对象。现在我的问题是,我知道这些列表会随着时间的推移而增长,因此它们需要增长空间。到目前为止,我存储列表以便在对象增长时不需要在对象周围移动的最佳想法是为每个列表分配一个 id,就像对象一样,以便它们可以像要查找的对象一样在表中查找它们在磁盘上。

现在每个列表部分将有一个设置的分配空间来存储 10 个对象,然后如果它包含更多对象,最后将是下一个列表部分的 id。这似乎是一种不错的方法来处理不断增长的对象,但我想知道是否有更好的方法。我会将索引存储在内存中(空间允许),因此给定一个对象 ID,查找在内存中,然后需要 1 个 I/O 才能找到从磁盘获取它的数据和列表 ID。然后对于您要遍历的每个列表,如果块被缓存,则列表中的每 10 个对象或更少的对象将进行另一次查找和 I/O。

I/O 的数量并不可怕,我会尝试保持列表部分的局部性以消除不必要的 I/O,但是有更好的方法吗?我是否应该尝试将列表与对象分开存储,或者我应该考虑将它们与对象数据一起存储的方法。我对此的担心是,随着一个列表的增长,它会进入另一个列表,然后需要被分割,这可能会变得更加复杂。任何建议都表示赞赏并提前感谢。

【问题讨论】:

    标签: database list object disk-io


    【解决方案1】:

    拥有这些可扩展列表的想法很好。我认为您的解释缺少一些细节(即:有序列表与否,尝试将列表与对象分开是什么意思,这些列表的图表可能会有所帮助)。

    我会在内存中保留一个排序索引以便快速访问。索引将具有列表 ID 和磁盘上的位置。如果您对范围查询感兴趣,请使用 B 树方法,否则您可以使用哈希图来存储这些索引。

    如果您在列表上进行搜索,进一步的改进是保持它们排序...或至少半排序,以便您可以将相似的列表分组到同一个块中。如果您经常缓存到内存中说每个块的边界(值为 b/w 1-9、10-25 等的节点),这将加快在列表中的搜索速度。合并排序可能是列表的最佳排序。甚至更好的是,当您在列表中插入节点时,插入正确的位置,以便列表始终排序。然后用二分查找查找。如果数据未正确索引且未排序,您将多次访问磁盘进行查询,在这种情况下,由于磁盘时间,您使用的任何搜索都会为您提供线性时间。

    您还可以缓存 10% 最常查找的节点/列表的数据节点。

    根据这些列表的大小(以及您拥有的多少个块),您可以使用一些 RAID,以便获得一些并行读取/写入。

    【讨论】:

    • 我已经完成了大部分的实现。我最终决定使用集合而不是列表,因为我还需要哈希图,所以我为Map<K,V> 接口创建了自己的实现,除了 K,V 扩展 PersistentObject。然后我根据地图制作了一套作为背景。然后我将 PersistentObject 实现为一个使用反射来查找所有子类非瞬态字段并相应地保存它们的类,这样每个对象就不需要定义它自己的保存方式。总的来说,一切都很顺利。不过,我会记住你的答案,以便稍后进行缓存。
    • @user1084563 我喜欢 :) 你用这个系统做什么,如果你不介意我问的话。
    • 它实际上是一个用于存储语义网络的系统,该网络由使用 stanford nlp 工具包从自然语言输入中提取的信息构建而成。显然我可以使用数据库,但我决定自己编写存储作为我的数据库系统课程的一个副项目,我希望它尽可能动态,以便可以轻松地将持久数据类型交换为现有的主内存数据类型。此外,我希望对象定义的更改能够自动反映在存储中,这样对象就不必重新定义如何保存和加载自身。
    猜你喜欢
    • 2017-06-01
    • 2010-09-20
    • 2017-01-10
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 1970-01-01
    • 2016-12-25
    相关资源
    最近更新 更多