【发布时间】:2016-11-15 08:54:44
【问题描述】:
我有一个小型自定义数据库,我很好奇我是否应该以不同的方式处理数据更新:
目前我在 HD 上写入文件的结构是这样组成的:
Header(uniqueID,lengthOfDataInBytes,HeaderChecksum)
data
文件中有数千个这样的结构,数据部分平均有几百 kb。
如果我想更新/删除一个结构,我将以下所有结构读入内存,将它们写回我要更新/删除的结构开头的文件,清除我的索引器字典,然后附加更新的结构到文件末尾/什么都不做,让我的索引器再次运行整个文件。
这很好用,因为通常的文件大小约为 2Gbyte,并且更新的结构最有可能再次更新,因此不太可能在文件的开头不断更新结构。
但是,如果用户的文件大小比他的 RAM 大,我想这种情况会破坏我当前的更新/删除部分设置?
是否存在解决此问题的常见做法? 我想到的替代方案是:
使用“跳过此扇区”命令覆盖更新/删除结构的标题,将其作为垃圾代码保存在文件中,并将更新版本附加到末尾。 好处是我不必阅读以下所有部门。缺点是,我必须决定运行清理例程的好时机。
将数据库拆分为多个固定大小的文件,并将所需扇区的文件指针添加到我的索引器中。保持我旧的更新/删除方式。 优点:不需要进一步的清理工作 缺点:增加了另一个抽象层次
这通常是如何处理的?有没有更好的解决方案来解决这个问题?
编辑:请停止提示使用 sql。 我试过了,它的性能比我目前工作的解决方案差得多。 如果这令人难以置信,请考虑一下:
- 两侧没有冗余内存缓冲区。
- 我持有缓冲数据的引用。
- 我不需要在查询字符串上浪费额外的周期。
- 我可以通过已经对已经读取/即将写入的数据进行一些反/序列化工作来填补 HD 读取/写入时间的延迟,而不必等待数据库返回我的查询结果 /在我将它传递给 sql 之前必须完成所有这些。(这是迄今为止影响最大的)
【问题讨论】:
-
将所有内容加载到 RAM 中的动机是什么?这种操作最高效的选项是内存映射文件 (
FileChannel#map)。 -
出于好奇:您为什么不使用“真正的”数据库引擎?像 sqlite 这样的东西似乎是您想要使用的。
-
@SteffenWinkler 因为我试过了,它的速度慢了大约 100 倍
-
@MarkoTopolnik 我没有将所有内容都加载到内存中。当我阅读时,我只读取想要的扇区,当我写入时,我只读取我想要更新的扇区之后的扇区
-
@user3488765 我非常确信:如果您的实验表明使用数据库会使您的速度降低 100 倍……那么您做错了什么。我发现您通过重新发明自己的数据库层来“手动”处理如此大量数据的方法是“一个有趣的想法”。
标签: java c# database performance