数据库中的可变长度文件写入

问题描述 投票:1回答:1

出于学习/实验目的,我试图模仿我从研究数据库中学到的一些技巧。我很好奇MySQL(以及其他数据库)如何解决这个特殊问题。

所以我正在编写一个应用程序,与其他数据库一样,将记录并排存储在一个文件中。我使用另一个文件来索引记录的位置,以便快速查找它们。一切正常,直到我需要更新一个比当前版本更长的行。我有一些想法,但似乎没有一个对性能友好。

假设我想更新1,000条记录中的记录200。在我的逻辑中,我将文件光标放在行开始的位置,然后写入数据。假设该行的当前版本是100字节长(并且从下一条记录开始的第101字节开始)。新数据长度为150个字节,因此只需使用文件光标写入就会有效地覆盖下一个记录中的字节。

据我所知,你不能从光标“推送”文件中的数据 - 如果我能,它似乎不是最性能友好的操作。

我可以选择附加新数据并用NULL字节替换当前行。但这似乎是a)浪费空间b)再次,需要大量的机器工作来重建文件而没有NULL字节

然后就是碎片整理的选择,但我还没准备好去那个方向。

有谁知道其他数据库如何处理这个问题?

mysql database file cursor fwrite
1个回答
2
投票

其他数据库以多种方式处理此问题。我可以回答MySQL。

  • 第一次将记录写入文件中的某个空间时,请留出一些额外的空间。将存储组织为16KB的“页面”,其中有几个记录适合。但是最初将1/16空间留空,以允许行扩展。每个页面都按需加载到RAM中,并且在将页面写回磁盘之前可以重新组织其中的记录。
  • 如果记录超出页面中的空间,则可能会将它们分开。某些记录可能会重新定位到其他新页面,这些新页面可能相距甚远。跟踪记录位置的索引不需要记录相邻。
  • 从所有记录重组和拆分中留下的空白空间导致一些碎片,但它可能只占整个存储的一小部分,所以我们不担心它。最终,碎片可能会变得更糟,所以不时将所有记录的新副本制作成一组新页面,更有效地重新组织,以替换原始页面,这是一个好主意。你应该多久这样做取决于你在数据库中完成了多少活动,所以没有严格的规则。
  • 另一个可能有用的新功能称为sparse fileshole-punching。传统上,无论是否在这些字节中存储有用数据,文件的所有连续字节都占用磁盘空间。但是,如果文件中的间隙可以被视为可用磁盘空间呢?那你就不关心碎片了。所有文件系统都不支持这种情况,“漏洞”通常限于文件系统块大小的倍数(例如4KB)。 MySQL 5.7在其page compression功能中使用了打孔功能。 MySQL仍然以16KB页面存储数据,但您可以在页面内启用可选的数据压缩。如果压缩留下4KB的空隙(文件系统块的大小),它会将其视为一个漏洞,并为其释放文件系统存储空间。

还有许多其他技巧可能。不值得尝试将存储优化到字节,因为只要您这样做,另一个数据更新将需要您撤消它。优化快速更新通常比完全紧凑的存储更好。一切都归结为不同类型的效率(例如,速度与存储)之间的权衡,您必须做出一些关于什么对您的数据库更重要的决定。

© www.soinside.com 2019 - 2024. All rights reserved.