【问题标题】:Is there a proper way to manage data removal from a file? [closed]是否有适当的方法来管理从文件中删除数据? [关闭]
【发布时间】: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


【解决方案1】:

考虑将自定义文件格式替换为实际数据库,例如 SQLite。 (或者甚至可能是客户端/服务器数据库,例如 MySQL 或 SQL Server。)

以额外的实施工作为代价,您可以获得以下好处:

  • 经过测试和验证的代码可以处理您的数据。
  • 随机访问数据(数据库为您建立记录索引)意味着快速插入/更新/删除。

在您的情况下,uniqueID 将成为表的主键,您可以删除数据列的校验和和长度,并使数据列成为 blob 或文本(取决于内容)。

【讨论】:

  • 试过了,慢了一百倍左右,而且还需要客户设置db
  • @user3488765 我无法想象缓慢是由引擎本身(尤其不是客户端/服务器引擎)引起的,但更多是由特定用例引起的(我们需要更多细节,它是一个候选者)对于 SQLite - 具体问题)。此外,SQLite 不需要设置。如果您将驱动程序与您的应用程序一起分发,它是can create databases on its own
  • @user3488765 有大量内部使用数据库的应用程序;无需要求其用户安装/设置与数据库相关的任何内容。您可以向用户隐藏所有复杂性。当然,这是工作,但我认为:值得付出努力。
  • @user3488765 在内部,数据库在“页面”中组织数据。页面是引擎从磁盘写入/读取的固定大小的数据段(例如 4KB)(一个页面可以包含多个数据行/记录,但数据库从不单独访问它们)。页面可以标记为已使用或未使用(因此插入数据会导致将新页面分配给 db 文件,而删除则会将它们标记为已释放)。页面以 B 树的形式组织。这就是它的要点,我建议在谷歌上搜索“数据库页面”——你会发现不同的引擎是如何做的。
  • @user3488765 我想说这是两者的混合。数据库使用在第一个要点中将页面标记为未使用(并准备好重用)的想法,但索引指向整个页面而不是单个文件位置的概念在第二个要点中更常见。但是,我不知道您的数据库中有多少条记录,但如果您要将每条记录保存在单独的文件中,请注意file system limitations
猜你喜欢
  • 1970-01-01
  • 2017-02-19
  • 2016-04-30
  • 1970-01-01
  • 2019-06-09
  • 2021-02-26
  • 1970-01-01
  • 2022-11-27
  • 1970-01-01
相关资源
最近更新 更多